字符串专项:CodeForces 235C

来源:互联网 发布:淘宝卫浴装修效果图 编辑:程序博客网 时间:2024/06/05 09:27

一道后缀自动机的算是模板题吧,可是我还是折腾了一个下午……总算对这个模板有了稍微深入的理解,debug了很久,也发现了不少的问题。现在算是基本会用后缀数组了。

#include <iostream>#include <cstdio>#include <cstring>#include <vector>using namespace std;const int maxn=2000010;const int sigma=26;int n,sz;struct state{    state *pre,*go[sigma];    int val,cnt,flag;    void clear()    {        pre=0;val=0;cnt=0;flag=0;        memset(go,0,sizeof(go));    }} *root,*last,st[maxn],*r[maxn];int t[maxn];void init(){    sz=0;    root=last=&st[sz++];    root->clear();}void extend(int w){    state *p=last;    state *np=&st[sz++];    np->clear();    np->val=p->val+1;    np->cnt=1;    while(p && p->go[w]==0)    {        p->go[w]=np;        p=p->pre;    }    if(p==0) np->pre=root;    else    {        state *q=p->go[w];        if(q->val==p->val+1) np->pre=q;        else        {            state *nq=&st[sz++];            *nq=*q;            nq->val=p->val+1;            nq->cnt=0;            q->pre=nq;            np->pre=nq;            while(p && p->go[w]==q)            {                p->go[w]=nq;                p=p->pre;            }        }    }    last=np;}char s[maxn];vector<int> v[maxn];int main(){    //freopen("in.txt","r",stdin);    scanf("%s",s);    int m=strlen(s);    init();    for(int i=0;i<m;i++) extend(s[i]-'a');//    for(int i=1;i<sz;i++) v[st[i].val].push_back(i);//    for(int i=m;i>=1;i--)//        for(int j=0;j<v[i].size();j++)//        {//            int x=v[i][j];//            if(st[x].pre) st[x].pre->cnt+=st[x].cnt;//        }    memset(t,0,sizeof(t));    for(int i=1;i<sz;i++) t[st[i].val]++;    for(int i=1;i<=m;i++) t[i]+=t[i-1];    for(int i=1;i<sz;i++) r[t[st[i].val]--]=&st[i];    for(int i=sz-1;i>0;i--)    {        //cout<<r[i]->cnt<<" "<<r[i]->val<<endl;        r[i]->pre->cnt+=r[i]->cnt;    }    scanf("%d",&n);    for(int i=1;i<=n;i++)    {        scanf("%s",s);        m=strlen(s);        for(int j=0;j<m;j++) s[j+m]=s[j];        s[2*m]=0;        state *p=root;        int len=0,ans=0;        for(int j=0;j<2*m;j++)        {            int w=s[j]-'a';            while(p && p->go[w]==0)            {                p=p->pre;len=p?p->val:0;            }            if(p==0)            {                p=root;                len=0;                continue;            }            p=p->go[w];len++;            if(len>=m)            {                state *tmp=p;                while(tmp->pre && tmp->pre->val>=m)                    tmp=tmp->pre;                if(tmp->flag!=i)                {                    tmp->flag=i;                    //cout<<j<<" "<<tmp->val<<" "<<tmp->cnt<<endl;                    ans+=tmp->cnt;                }            }            //cout<<j<<" "<<ans<<endl;        }        printf("%d\n",ans);    }    return 0;}