bzoj3172 [Tjoi2013]单词(SA+暴力,类似bzoj2754)

来源:互联网 发布:威联通nas网络存储 编辑:程序博客网 时间:2024/05/22 00:53

把所有单词连在一起,SA求出h数组,对于每一个单词看做一个询问,暴力往前往后扫,看有几个暴力统计即可。反正N才200

#include <cstdio>#include <cstring>#include <algorithm>#define N 1001000int nn,n=0,m=30,a[N],bel[N],qn[210];int count[N],tmp[N],rank[N<<1],rank1[N],sa[N],h[N];char s[N];int main(){//  freopen("a.in","r",stdin);    scanf("%d",&nn);    for(int i=1;i<=nn;++i){        scanf("%s",s+1);qn[i]=strlen(s+1);        for(int j=1;j<=qn[i];++j) a[++n]=s[j]-'a'+1,bel[n]=i;        a[++n]=++m;    }    for(int i=1;i<=m;++i) count[i]=0;    for(int i=1;i<=n;++i) count[a[i]]=1;    for(int i=1;i<=m;++i) count[i]+=count[i-1];    for(int i=n;i>=1;--i) rank[i]=count[a[i]];    int k=0;    for(int p=1;k!=n;p<<=1,m=k){        for(int i=1;i<=m;++i) count[i]=0;        for(int i=1;i<=n;++i) count[rank[i+p]]++;        for(int i=1;i<=m;++i) count[i]+=count[i-1];        for(int i=n;i>=1;--i) tmp[count[rank[i+p]]--]=i;        for(int i=1;i<=m;++i) count[i]=0;        for(int i=1;i<=n;++i) count[rank[tmp[i]]]++;        for(int i=1;i<=m;++i) count[i]+=count[i-1];        for(int i=n;i>=1;--i) sa[count[rank[tmp[i]]]--]=tmp[i];        memcpy(rank1,rank,sizeof(rank1));        rank[sa[1]]=k=1;        for(int i=2;i<=n;++i){            if(rank1[sa[i]]!=rank1[sa[i-1]]||rank1[sa[i]+p]!=rank1[sa[i-1]+p]) ++k;            rank[sa[i]]=k;        }    }k=0;    for(int i=1;i<=n;++i){        if(rank[i]==1){h[1]=0;continue;}        if(i==1||h[rank[i-1]]<=1) k=0;        if(k) --k;        while(a[i+k]==a[sa[rank[i]-1]+k]) ++k;        h[rank[i]]=k;    }    int id=1;    for(int i=1;i<=nn;++i){        int x=rank[id];        int l=x,r=x+1;        while(h[l]>=qn[i]) --l;        while(h[r]>=qn[i]) ++r;--r;        printf("%d\n",r-l+1);        id+=qn[i]+1;    }    return 0;}
原创粉丝点击