状态ans[i][j]表示长度为i的字符串能达到j状态(非危险结点)的数量。
那么状态方程为ans[i+1][next]=ans[i+1][next]+ans[i][j],因为从i长度的串过度到i+1长度的串需要转到j的下一状态,并且该长度该状态有很多不同的串可以达到,所以要相加。
那么最后只要把ans[n][j]状态加起来就可以了。
这题目既卡内存又卡时间。
<pre name="code" class="cpp">//
// main.cpp
// Richard
//
// Created by 邵金杰 on 16/9/6.
// Copyright © 2016年 邵金杰. All rights reserved.
//
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
using namespace std;
struct node{
node *child[55];
node *pre;
bool badnode;
void intial(){
memset(child,0,sizeof(child));
pre=NULL;
badnode=false;
}
}tree[105];
struct Bigint{
int num[300];
int len;
void intial(){
memset(num,0,sizeof(num));
len=0;
}
void output(){
for(int i=len-1;i>=0;i--)
cout<<num[i];
cout<<endl;
}
}dp[55][105];
char s[55],str[20];
int n,m,p;
int ncount;
map<char,int> ha;
void Insert(node *p,char *ss)
{
for(;*ss;ss++)
{
int idx=ha[*ss];
if(p->child[idx]==NULL)
{
tree[ncount].intial();
p->child[idx]=tree+ncount;
ncount++;
}
p=p->child[idx];
}
p->badnode=true;
}
void BuildDFA()
{
for(int i=0;i<n;i++)
tree[0].child[i]=tree+1;
tree[0].pre=NULL;
tree[1].pre=tree;
queue<node *> q;
q.push(tree+1);
while(!q.empty())
{
node *proot=q.front();q.pop();
for(int i=0;i<n;i++)
{
node *p=proot->child[i];
if(p==NULL)
{
if(proot==tree+1)
proot->child[i]=tree+1;
else
proot->child[i]=proot->pre->child[i];
}
else
{
node *pre=proot->pre;
while(pre)
{
if(pre->child[i])
{
p->pre=pre->child[i];
if(p->pre->badnode)
p->badnode=true;
break;
}
else
pre=pre->pre;
}
q.push(p);
}
}
}
}
Bigint operator + (Bigint s1,Bigint s2)
{
if(s1.len<s2.len)
{
Bigint temp=s1;
s1=s2;
s2=temp;
}
int k=0;
for(int i=0,j=0;i<s1.len;i++,j++)
{
k+=s1.num[i]+s2.num[j];
s1.num[i]=k%10;
k/=10;
}
while(k)
{
s1.num[s1.len++]=k%10;
k/=10;
}
return s1;
}
void DP()
{
for(int i=0;i<=m;i++)
for(int j=0;j<ncount;j++)
dp[i][j].intial();
dp[0][1].num[dp[0][1].len++]=1;
for(int i=0;i<m;i++)
{
for(int j=1;j<ncount;j++)
{
for(int k=0;k<n;k++)
{
node *tmp=tree[j].child[k];
int next=(int)(tmp-tree);
if(tmp->badnode) continue;
dp[i+1][next]=dp[i+1][next]+dp[i][j];
}
}
}
Bigint result[105];
for(int i=0;i<50;i++) result[i].intial();
int k=0;
result[0].num[0]=0;
result[0].len++;
for(int i=1;i<ncount;i++)
if(!tree[i].badnode) k++,result[k]=dp[m][i]+result[k-1];
result[k].output();
}
int main()
{
while(scanf("%d%d%d",&n,&m,&p)!=EOF)
{
ha.clear();
ncount=2;
tree[0].intial();
tree[1].intial();
scanf("%s",s);
for(int i=0;i<strlen(s);i++)
ha[s[i]]=i;
for(int i=0;i<p;i++)
{
scanf("%s",str);
Insert(tree+1,str);
}
BuildDFA();
DP();
}
return 0;
}