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 }