字符串(后缀自动机):COGS 2399. 循环同构

  这道题直接看代码吧。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 using namespace std;
 5 const int maxn=2000010;
 6 int fa[maxn],len[maxn],rit[maxn],w[maxn],sa[maxn];
 7 int n,Q,cnt,lst,ch[maxn][26],vis[maxn];
 8 char s[maxn];
 9 struct SAM{
10     SAM(){
11         memset(fa,0,sizeof(fa));
12         memset(len,0,sizeof(len));
13         memset(rit,0,sizeof(rit));
14         cnt=lst=1;
15     }
16     
17     void Insert(int c){
18         int p=lst,np=lst=++cnt;len[np]=len[p]+1;
19         while(p&&!ch[p][c])ch[p][c]=np,p=fa[p];
20         if(!p)fa[np]=1;
21         else{
22             int q=ch[p][c];
23             if(len[p]+1==len[q])fa[np]=q;
24             else{
25                 int nq=++cnt;len[nq]=len[p]+1;
26                 memcpy(ch[nq],ch[q],sizeof(ch[q]));
27                 fa[nq]=fa[q];fa[q]=fa[np]=nq;
28                 while(ch[p][c]==q)ch[p][c]=nq,p=fa[p];
29             }
30         }
31     }
32     
33     void Prepare(){
34         //rit[1]=1;
35         for(int i=1,p=1;i<=n;i++)
36             rit[p=ch[p][s[i]-'a']]+=1;
37         for(int i=1;i<=cnt;i++)w[len[i]]+=1;
38         for(int i=1;i<=cnt;i++)w[i]+=w[i-1];
39         for(int i=1;i<=cnt;i++)sa[--w[len[i]]]=i;
40         for(int i=cnt;i;i--)rit[fa[sa[i]]]+=rit[sa[i]];
41     }
42     
43     void Solve(int tim){
44         scanf("%s",s+1);n=strlen(s+1);
45         for(int i=1;i<=n;i++)s[n+i]=s[i];
46         int p=1,ans=0,l=0;
47         for(int i=1,c;i<2*n;i++){
48             c=s[i]-'a';
49             while(p!=1&&!ch[p][c])
50                 {p=fa[p];l=len[p];}
51             if(!ch[p][c])l=0;
52             else{p=ch[p][c];l+=1;}
53             
54             if(l>=n){
55                 while(len[fa[p]]>=n)p=fa[p],l=len[p];
56                 if(vis[p]!=tim)vis[p]=tim,ans+=rit[p];
57             }
58         }
59         printf("%d\n",ans);
60     }
61 }sam;
62 int main(){
63     freopen("rotate.in","r",stdin);
64     freopen("rotate.out","w",stdout);
65     scanf("%s%d",s+1,&Q);n=strlen(s+1);
66     for(int i=1;i<=n;i++)sam.Insert(s[i]-'a');
67     sam.Prepare();while(Q--)sam.Solve(Q+1);
68     return 0;
69 }

 

posted @ 2016-07-22 22:08  TenderRun  阅读(307)  评论(0编辑  收藏  举报