Description
某日mhy12345在教同学们写helloworld,要求同学们用程序输出一个给定长度的字符串,然而发现有些人输出了一些“危险”的东西,所以mhy12345想知道对于任意长度n的小写字母字符串,不包含危险串的字符串个数
Input
多组数据,以EOF结束。对于每组数据,第一行一个数n,表示字符串的长度,第二行一个字符串str表示危险串。
Output
对于每组数据,输出一个整数表示答案 mod (10^9+7)的值。
Sample Input
5
a
Sample Output
9765625
Data Constraint
对于10%的数据,|str|=1
对于另30%的数据,n<=5
对于另30%的数据,危险串不存在相同字符
对于100%的数据,0<=|str|<=100,0<=n<=10000
真是水的不行。。快速列出方程式f[i,j]表示原串匹配到i位,危险串匹配到j位,然后直接DP
方程式是f[i+1,g[j,k]]+=f[i,j];g[j,k]表示第j+1位失配时那个失配数组指向的位置,k是字符。。然而我考场上算了算,状态数还没有转移就达到了2e7(100*10000*26),这不是会爆?于是用了矩阵快速幂来优化状态转移,,结果被逗了。。还打错了,只有30分。。MDZZ。。
uses math;
const mo=1000000007;
var
i,j,k,p,n,m:longint;
s:ansistring;
c:char;
f:array[0..10000,0..100]of longint;
next:array[0..100000]of longint;
g:array[0..10000,0..26]of longint;
ans:longint;
begin
assign(input,'helloworld.in');
assign(output,'helloworld.out');
reset(input);
rewrite(output);
while true do
begin
readln(n);
readln(s);
if n=0then break;
m:=length(s);
s:=s+'#';
fillchar(f,sizeof(f),0);
fillchar(next,sizeof(next),0);
j:=0;
for i:=2 to m do
begin
while(j>0)and(s[i]<>s[j+1])do j:=next[j];
if s[i]=s[j+1] then inc(j);
next[i]:=j;
end;
fillchar(g,sizeof(g),0);
for i:=0 to m-1 do
begin
for c:='a'to'z' do
begin
j:=i;
while(j>0)and(s[j+1]<>c)do j:=next[j];
if s[j+1]=c then inc(j);
g[i,ord(c)-97]:=j;
end;
end;
f[0,0]:=1;
for i:=1 to n do
begin
for j:=min(i,m)-1 downto 0 do
begin
for k:=0 to 25 do
f[i,g[j,k]]:=(f[i,g[j,k]]+f[i-1,j])mod mo;
end;
end;
ans:=0;
for i:=0 to m-1 do
ans:=(ans+f[n,i])mod mo;
writeln(ans);
end;
end.