求:$${prod _{i=1}^{L}num[i]\%(1e9+7)}$$,${numleft [ i ight ]}$表示:由字符串$S$的前$i$个字符构成的子串中,既是它的前缀,又是它的后缀,并且互不重合的字符串的个数。
利用KMP算法求出$next$数组,同时求出$cnt$数组,$cnt$数组定义为:由字符串$S$的前$i$个字符构成的子串中,既是它的前缀,又是它的后缀,可以的字符串的个数。
${cnt[i]=cnt[next[i]]+1}$
然后对于每一个位置,我们再做一遍形如找$next$数组的过程,但是这个时候指针一定要沿着$next$数组跳回到${left lfloor frac{i}{2} ight floor}$之前,我们知道对应点的$cnt$,那么这就满足了互不重合的条件,直接算贡献即可。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<vector> 5 #include<cstdlib> 6 #include<cmath> 7 #include<cstring> 8 using namespace std; 9 #define maxn 1001000 10 #define llg long long 11 #define md 1000000007 12 #define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout); 13 llg n,m,next[maxn],T; 14 char s[maxn]; 15 llg cnt[maxn];//既是1~i的后缀又是它的前缀的字符串个数 16 17 void find_next() 18 { 19 llg k=0; 20 next[1]=0; cnt[1]=1; 21 for (llg i=2;i<=n;i++) 22 { 23 while (k && s[k+1]!=s[i]) k=next[k]; 24 if (s[k+1]==s[i]) k++; 25 next[i]=k; 26 cnt[i]=cnt[k]+1; 27 } 28 } 29 30 llg work() 31 { 32 llg k=0,ans=1; 33 for (llg i=2;i<=n;i++) 34 { 35 while (k && s[k+1]!=s[i]) k=next[k]; 36 if (s[k+1]==s[i]) k++; 37 while (k*2>i) k=next[k]; 38 ans=ans*(cnt[k]+1); 39 ans%=md; 40 } 41 return ans; 42 } 43 44 int main() 45 { 46 yyj("a"); 47 cin>>T; 48 while (T--) 49 { 50 scanf("%s",s+1); 51 n=strlen(s+1); 52 find_next(); 53 printf("%lld ",work()); 54 } 55 return 0; 56 }