现在看来真是自然无比。。。
首先我们先求出(next)数组,然后不考虑那个不重叠的限制
换句话说现在可以搞一个(num')出来,容易发现对于一个前缀(i)的(next_i)它满足题目的要求,同时(next_{next_i})显然也是满足的,再往下推同理
然后我们发现(num')数组可以和(next)数组一起递推出来,非常方便,那么现在就是怎么求(num)的问题了
随手画个图,假设我们现在对于位置(i)用(next)向前跳,直到跳到第一个位置(j)满足(jlelfloor frac{i}{2} floor),那么这个时候应该是这样:
此时显然从(j)开始往前跳(next)的串都满足要求,并且(num'_j=num_i)(因为不会重复了,(j)的前缀已经和(i)的后缀相同)
然后就做完了,复杂度(O(n))
#include<cstdio>
#include<cstring>
using namespace std;
const int N=1000005,mod=1e9+7;
char s[N];
int n,next[N],num[N],ans,t;
inline void get_next(char *s)
{
register int i; int len=0;
for (i=2;i<=n;++i)
{
while (len&&s[i]!=s[len+1]) len=next[len];
if (s[i]==s[len+1]) ++len; next[i]=len; num[i]=num[len]+1;
}
}
inline void get_num(char *s)
{
register int i; int len=0;
for (i=2;i<=n;++i)
{
while (len&&s[i]!=s[len+1]) len=next[len];
if (s[i]==s[len+1]) ++len;
while ((len<<1)>i) len=next[len];
ans=1LL*ans*(num[len]+1)%mod;
}
}
int main()
{
scanf("%d",&t); while (t--)
{
scanf("%s",s+1); n=strlen(s+1); ans=1;
memset(next,0,sizeof(next)); num[1]=1;
get_next(s); get_num(s); printf("%d
",ans);
}
return 0;
}