范围很狗,不要轻信!
https://www.luogu.org/problemnew/show/P2375
我们大家都知道 的数组吧(不知道也无所谓)
其定义是:
在字符串从第1位开始长度为的子串中,既是前缀又是后缀的最长的子串的长度(可以重叠)称为
先定义这样一个数组:
在字符串从第1位开始长度为的子串中,既是前缀又是后缀的最长的子串的长度(不可重叠)称为
求
˼·
唉呀妈呀,好麻烦啊,我们充分理解之后就会发现
所有的两倍均小于,所以我们就可以加个特判就行了
#include<cstdio> #include<cstring> #define mod 1000000007 using namespace std;int kmp[1000001],num[1000001],t,n; long long ans; char a[1000001]; int main() { scanf("%d",&t);//t组数据 while(t--) { scanf("%s",a);n=strlen(a); kmp[0]=-1; kmp[1]=0;num[0]=0; num[1]=1;//初始化 ans=1;//初始化 for(int i=1,j=0;i<n;) if(j==-1||a[i]==a[j]) kmp[++i]=++j,num[i]=num[j]+1; else j=kmp[j];//kmp算法 for(int i=1,j=0;i<n;i++) { while(j>=0&&a[i]!=a[j]) j=kmp[j]; j++; while((j<<1)>(i+1)) j=kmp[j];//代码核心 ans*=(long long)num[j]+1; ans%=mod; } printf("%lld\n",ans);//输出 } }
文章来源: 【改造KMP】洛谷P2375 动物园