题意:定义num[i]表示:对字符串S的前i个字符组成的子串,既是它的前缀又是它的后缀且该前缀与后缀不重叠,满足条件的字符串的数量记做num[i],ans等于(num[i]+1)的累乘,对1000000007 取模
一看就是kmp..
再一看数据范围必须O(n)...所以一开始naive的对每个i都递归一下i=next[i]是妥妥的TLE的 QAQ
令 num[i]表示既是i前缀又是i后缀的子串个数
由kmp的性质可得 num[i]=num[next[i]]+1
当然这个答案不一定是合法的,只需要从num[i-1]开始运用kmp的next往前跳,跳到第一个不大于(i/2)的位置p,ans*=num[p]+1
const
mo=1000000007;
var
t,p1,p2,l :longint;
ans :qword;
i :longint;
s :ansistring;
next,num :array[0..1000010] of longint;
begin
readln(t);
while (t>0) do
begin
dec(t);
readln(s);
l:=length(s);
fillchar(next,sizeof(next),0);
fillchar(num,sizeof(num),0);
p1:=0; p2:=0; ans:=1; num[1]:=1;
for i:=2 to l do
begin
while (p1<>0) and (s[i]<>s[p1+1]) do p1:=next[p1];
if (s[i]=s[p1+1]) then
begin
inc(p1);
next[i]:=p1;
end else next[i]:=0;
//
num[i]:=num[next[i]]+1;
while (p2<>0) and (s[i]<>s[p2+1]) do p2:=next[p2];
if s[i]=s[p2+1] then inc(p2);
while (p2>(i>>1)) do p2:=next[p2];
ans:=(ans*int64(num[p2]+1)) mod mo;
end;
writeln(ans);
end;
end.
PS:mdzz,一开始看错题了,把题目中新定义的num数组当成“对字符串S的前i个字符组成的子串,既是它的前缀又是它的后缀且该前缀与后缀不重叠,满足条件的最长字符串”,对于这道看错了的题,答题思路和看对了的题是一样的,就是对num数组的定义是不一样的,这里定义num数组为看错了的所求,每一次跳到上一次的num[i-1]+1的位置,然后用next往前跳到第一个满足条件的位置就记录下来就可以了 。更尴尬的是这样错误的解法居然和样例只有最后一个字符串不一样,瞬间怀疑样例....
——by Eirlys