【jzoj3887】【字符串查询 】【二分查找】【可持久化trie】

来源:互联网 发布:怎样查看淘宝账号等级 编辑:程序博客网 时间:2024/05/14 07:41

题目大意

给定n个字符串和q个询问

每次询问在这n个字符串中,有多少个字符串同时满足

1. 字符串a是它的前缀

2. 字符串b是它的后缀

解题思路

先对字符串排序,倒着建可持久化trie,二分查找前缀,后缀在线查询。

code

#include<cmath>#include<cstdio>#include<cstring>#include<algorithm>#define LF double#define LL long long#define min(a,b) ((a<b)?a:b)#define max(a,b) ((a>b)?a:b)#define fo(i,j,k) for(int i=j;i<=k;i++)#define fd(i,j,k) for(int i=j;i>=k;i--)using namespace std;int const maxn=5*1e4;int n,q,cnt,t[maxn*100+10],son[maxn*100+1][10];struct rec{    char s[101];    int len;};rec s[maxn+1],a,b;bool cmp(rec x,rec y){    int tmp=max(x.len,y.len);    fo(i,1,tmp)if(x.s[i]<y.s[i])return 1;    else if(x.s[i]>y.s[i])return 0;    return 0;}int cmp2(rec x,rec y,int tmp){    fo(i,1,tmp)if(x.s[i]>y.s[i])return 1;    else if(x.s[i]<y.s[i])return 0;    return 2;}void oper(int now,int pre,rec &s,int p,int lim){    t[now]=t[pre]+1;    fo(i,0,9)if(i!=s.s[p]-'a')son[now][i]=son[pre][i];    if((!p)||(p==lim))return;    if(!son[now][s.s[p]-'a'])son[now][s.s[p]-'a']=++cnt;    oper(son[now][s.s[p]-'a'],son[pre][s.s[p]-'a'],s,p-1,lim);}int qury(int now,rec &s,int p,int lim){    if((!p)||(p==lim))return t[now];    return qury(son[now][s.s[p]-'a'],s,p-1,lim);}int main(){    freopen("d.in","r",stdin);    freopen("d.out","w",stdout);    scanf("%d%d\n",&n,&q);    fo(i,1,n)scanf("%s\n",&s[i].s[1]),s[i].len=strlen(&s[i].s[1]);    sort(s+1,s+n+1,cmp);    cnt=n;    fo(i,1,n){        if(i==30000){            int bb;            bb++;        }        oper(i,i-1,s[i],s[i].len,s[i].len-100);    }    fo(i,1,q){        scanf("%s\n",&a.s[1]),a.len=strlen(&a.s[1]);        scanf("%s\n",&b.s[1]),b.len=strlen(&b.s[1]);        int l=1,r=n,mid;        while(l!=r){            mid=(l+r)/2;            if(cmp2(s[mid],a,a.len))r=mid;            else l=mid+1;        }        if(cmp2(s[l],a,a.len)!=2){printf("0\n");continue;}        int ans=qury(l-1,b,b.len,b.len-100);        l=1,r=n;        while(l!=r){            mid=(l+r)/2;            if(cmp2(s[mid],a,a.len)==1)r=mid;            else l=mid+1;        }        if((l==n)&&(cmp2(s[l],a,a.len)!=1))l++;        ans=qury(l-1,b,b.len,b.len-100)-ans;        printf("%d\n",ans);    }    return 0;}
0 0
原创粉丝点击