描述
小Hi平时的一大兴趣爱好就是演奏钢琴。我们知道一段音乐旋律可以被表示为一段数构成的数列。
小Hi发现旋律可以循环,每次把一段旋律里面最前面一个音换到最后面就成为了原旋律的“循环相似旋律”,还可以对“循环相似旋律”进行相同的变换能继续得到原串的“循环相似旋律”。
小Hi对此产生了浓厚的兴趣,他有若干段旋律,和一部音乐作品。对于每一段旋律,他想知道有多少在音乐作品中的子串(重复便多次计)和该旋律是“循环相似旋律”。
输入
第一行,一个由小写字母构成的字符串S,表示一部音乐作品。字符串S长度不超过100000。
第二行,一个整数N,表示有N段旋律。接下来N行,每行包含一个由小写字母构成的字符串str,表示一段旋律。所有旋律的长度和不超过 100000。
输出
输出共N行,每行一个整数,表示答案。
Sample Input
abac 3 a ab ca
Sample Output
2 2 1
一个endpos只能被寻找到一次
1 #pragma GCC optimize(2) 2 #pragma G++ optimize(2) 3 #include<cstring> 4 #include<cstdio> 5 #include<cmath> 6 #include<iostream> 7 #include<algorithm> 8 #include<queue> 9 10 #define ll long long 11 #define N 300007 12 using namespace std; 13 inline int read() 14 { 15 int x=0,f=1;char ch=getchar(); 16 while(!isdigit(ch)){if(ch==‘-‘)f=-1;ch=getchar();} 17 while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-‘0‘;ch=getchar();} 18 return x*f; 19 } 20 21 int n; 22 struct sam 23 { 24 int cnt,last; 25 int c[N][26],fa[N],mx[N],endpos[N]; 26 sam(){cnt=last=1;} 27 void extend(int x) 28 { 29 int p=last,np=last=++cnt;mx[np]=mx[p]+1;endpos[np]=1; 30 while(p&&!c[p][x]) 31 { 32 c[p][x]=np; 33 p=fa[p]; 34 } 35 if(!p)fa[np]=1; 36 else 37 { 38 int q=c[p][x]; 39 if(mx[q]==mx[p]+1)fa[np]=q; 40 else 41 { 42 int nq=++cnt;mx[nq]=mx[p]+1; 43 memcpy(c[nq],c[q],sizeof(c[q])); 44 fa[nq]=fa[q]; 45 fa[q]=fa[np]=nq; 46 while(c[p][x]==q)c[p][x]=nq,p=fa[p]; 47 } 48 } 49 } 50 int now=1,pre=0,du[N];queue<int>q[2]; 51 void init_endpos() 52 { 53 for (int i=1;i<=cnt;i++) 54 if(fa[i])du[fa[i]]++; 55 for (int i=1;i<=cnt;i++) 56 if(!du[i])q[pre].push(i); 57 while(!q[pre].empty()) 58 { 59 while(!q[pre].empty()) 60 { 61 int x=q[pre].front();q[pre].pop(); 62 endpos[fa[x]]+=endpos[x]; 63 du[fa[x]]--; 64 if(!du[fa[x]])q[now].push(fa[x]); 65 } 66 swap(now,pre); 67 } 68 } 69 int u=1,l=0;ll ans; 70 bool flag[N]; 71 void dp(int x,int n) 72 { 73 while(u&&!c[u][x])u=fa[u],l=mx[u]; 74 if(!u)u=1,l=0; 75 else u=c[u][x],l++; 76 if(l>n)while(mx[fa[u]]>=n)u=fa[u],l=mx[u]; 77 if(l>=n&&!flag[u]) 78 { 79 flag[u]=true; 80 ans+=endpos[u]; 81 } 82 } 83 void init() 84 { 85 printf("%lld\n",ans); 86 ans=0,u=1,l=0; 87 memset(flag,0,sizeof(flag)); 88 } 89 }sam; 90 char s[N],T[N]; 91 92 int main() 93 { 94 scanf("%s",s+1);int len=strlen(s+1); 95 for (int i=1;i<=len;i++)sam.extend(s[i]-‘a‘); 96 sam.init_endpos(); 97 n=read(); 98 while(n--) 99 { 100 scanf("%s",T+1); 101 len=strlen(T+1); 102 for (int i=1;i<=len;i++) 103 T[i+len]=T[i]; 104 len=len*2-1; 105 for (int i=1;i<=len;i++) 106 sam.dp(T[i]-‘a‘,(len+1)/2); 107 sam.init(); 108 } 109 }