https://www.lydsy.com/JudgeOnline/problem.php?id=3670
https://www.luogu.org/problemnew/show/P2375#sub
我已经懒得吐槽我有多笨了……
题目明示先求nxt数组绝对没错。
那么不难发现,当我们不考虑重合的时候,nxt[i]是一个合法的前后缀,同时nxt[nxt[i]]也是(画个图就明白了)……以此类推。
于是num数组统计如此递归下去的nxt的个数和,显然有num[i]=num[nxt[i]]+1。
接下来考虑重合情况,我们只需要将i不断跳nxt直到i小于当前串的一半即可,此时的num[i]即为答案。
#include<cmath> #include<queue> #include<cstdio> #include<cctype> #include<vector> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int N=1e6+5; const int p=1e9+7; char s[N]; int nxt[N],num[N]; void getnxt(int m){ for(int i=2,j=0;i<=m;i++){ while(j&&s[i]!=s[j+1])j=nxt[j]; if(s[i]==s[j+1])j++; nxt[i]=j;num[i]=num[j]+1; } } int main(){ int t,m; scanf("%d",&t); while(t--){ int ans=1; memset(nxt,0,sizeof(nxt)); memset(num,0,sizeof(num)); cin>>s+1;m=strlen(s+1); num[0]=0;num[1]=1; getnxt(m); for(int i=2,j=0;i<=m;i++){ while(j&&s[i]!=s[j+1])j=nxt[j]; if(s[i]==s[j+1])j++; while(j*2>i)j=nxt[j]; ans=(ll)ans*(num[j]+1)%p; } printf("%d ",ans); } return 0; }
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++