[bzoj3670]动物园

首先计算出s数组,s表示可以重复的前缀等于后缀的个数,显然有s[i]=s[next[i]]+1,因为有且仅有nextnext满足这个条件。

然后直接暴力枚举所有next,直到它小于i的一半,这个时间复杂度就是o(n)

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int t,ans,k,sum[1000005],nex[1000005];
 4 char s[1000005];
 5 int main(){
 6     scanf("%d",&t);
 7     while (t--){
 8         scanf("%s",s);
 9         k=0;
10         memset(nex,0,sizeof(nex));
11         ans=sum[1]=1;
12         for(int i=1;s[i];i++){
13             while ((k)&&(s[k]!=s[i]))k=nex[k];
14             if (s[k]==s[i])k++;
15             nex[i+1]=k;
16             sum[i+1]=sum[k]+1;
17         }
18         k=0;
19         for(int i=1;s[i];i++){
20             while ((k)&&(s[k]!=s[i]))k=nex[k];
21             if (s[k]==s[i])k++;
22             while (2*k>i+1)k=nex[k];
23             ans=ans*(sum[k]+1LL)%1000000007;
24         }
25         printf("%d\n",ans);
26     }
27 }
View Code

 

posted @ 2019-07-28 10:36  PYWBKTDA  阅读(135)  评论(0编辑  收藏  举报