描述
小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 }
来源:oschina
链接:https://my.oschina.net/u/4409656/blog/4054951