题目链接
http://www.lydsy.com/JudgeOnline/problem.php?id=3670
思路
为了方便叙述,下面所说的前缀
i
就是字符串中的区间
根据KMP定义,
next[i]=j
表示
前缀j
满足既是前缀
i
的前缀,又是前缀
然后我们可以根据
cnt[1]=1
cnt[i]=cnt[next[i]]+1
然后我们可以通过
cnt[]和next[]
数组得到
num[]
数组。具体做法是,对于每个
i>=2
(
i=1
时显然
num[i]=0
),通过沿着
next[]
指针向前走找到最大的
j
,
代码
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#define MAXN 1000100
#define MOD 1000000007
using namespace std;
typedef long long int LL;
LL ans=0;
char s[MAXN];
int next[MAXN],cnt[MAXN]; //cnt[i]=既是1~i的后缀又是它的前缀的字符串个数
void getnext(char str[],int len)
{
int k=0;
next[1]=0;
cnt[1]=1; //!!!!!!
for(int i=2;i<=len;i++)
{
while(k>0&&str[k+1]!=str[i]) k=next[k];
if(str[k+1]==str[i]) k++;
next[i]=k;
cnt[i]=cnt[k]+1;
}
}
LL work(char str[],int len)
{
int k=0;
ans=1;
for(int i=2;i<=len;i++) //用next[]和cnt[]数组求出num[i]
{
while(k&&str[k+1]!=str[i]) k=next[k];
if(str[k+1]==str[i]) k++;
while((k*2)>i) k=next[k];
ans=(ans*(cnt[k]+1))%MOD;
}
return ans;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%s",s+1);
int len=strlen(s+1);
getnext(s,len);
printf("%lld\n",work(s,len));
}
return 0;
}