luogu2375 动物园 (kmp)

首先求出fail数组,如果没有不重叠的限制的话,我们可以在求fail的时候递推出个数cnt[i]=cnt[fail[i]]+1(这个cnt是算上自己本身==自己本身的)

然后如果是要求不重叠的话,就是相当于一直跳fail,直到找到了一个长度不超过一半的fail,然后num[i]就是它

但如果直接暴力跳肯定是不行的

其实它跟求fail的时候是一样的,只要每次不重置那个指针,就把它当成在求fail一样往后匹配这一位,匹配完这一位再跳回到一半以下,就可以保证复杂度

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define ll long long int
 5 using namespace std;
 6 
 7 const int M=1e9+7,maxn=1000100;
 8 
 9 char s[maxn];
10 int fail[maxn],fulcnt[maxn];
11 int len;
12 ll ans=1;
13 
14 void getfail(){
15     int i,j,k;
16     fulcnt[1]=1;
17     for(i=2,j=0,k=0;i<=len;i++){
18         while(j && s[j+1]!=s[i])  j=fail[j];
19         while(k && s[k+1]!=s[i])  k=fail[k];
20         if(s[j+1]==s[i]) j++;
21         if(s[k+1]==s[i]) k++;
22         fail[i]=j;
23         fulcnt[i]=fulcnt[j]+1;
24         while(k&&k>i/2) k=fail[k];
25         ans=(ans*(fulcnt[k]+1))%M;
26     }
27 }
28 
29 int main(){
30     int t;
31     // freopen("testdata.in","r",stdin);
32     scanf("%d",&t);
33     for(;t;t--){
34         ans=1;
35         scanf("%s",s+1);
36         len=strlen(s+1);
37         memset(fail,0,sizeof(fail));
38         memset(fulcnt,0,sizeof(fulcnt));
39         getfail();
40         printf("%lld\n",ans);
41     }
42 }

 

posted @ 2018-09-25 21:36  Ressed  阅读(185)  评论(0编辑  收藏  举报