http://poj.org/problem?id=1625
AC自动机+DP+高精度
高精度的部分用c++里面的重载就可以
从树上节点转移到另一节点时 对其可行性的求解一定要注意
代码:
#include<iostream>
#include<cmath>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<algorithm>
#define LL long long
using namespace std;
const int INF=0x3f3f3f3f;
const int MOD=20090717;
const LL LMOD=100000;
const int N=55;
const int M=135;
const int K=50;
class BigInteger
{
public:
BigInteger()
{
memset(bint,0,sizeof(bint));
D=1000000000;
len=1;
}
BigInteger(int x)
{
memset(bint,0,sizeof(bint));
bint[0]=x;
D=1000000000;
len=1;
}
BigInteger operator +(const BigInteger &x)
{
BigInteger y;
int l;
for(l=0;l<x.len||l<len;++l)
y.bint[l]=x.bint[l]+bint[l];
y.len=l;
for(l=0;l<y.len;++l)
if(y.bint[l]>=D)
{++y.bint[l+1];y.bint[l]-=D;}
if(y.bint[l]>0)
++y.len;
return y;
}
//friend ostream& operator <<(ostream& output,const BigInteger& x);
int bint[50];
int len;
int D;
};
struct nodeTrie
{
int v;
int fail;
int next[K];
void initialize()
{
v=0;
fail=-1;
memset(next,-1,sizeof(next));
}
}trie[M];
int cnt,root;
char s[N];
int to[M][K];
BigInteger dp[N][M];
map<char,int>mt;
int getNewNode()
{
++cnt;
trie[cnt].initialize();
return cnt;
}
void addWord(int p,char *s,int k)
{
if(s[0]=='\0') return ;
for(int i=0;s[i]!='\0';++i)
{
if(trie[p].next[mt[s[i]]]==-1)
trie[p].next[mt[s[i]]]=getNewNode();
p=trie[p].next[mt[s[i]]];
}
trie[p].v=k;
}
void init(int p)
{
gets(s);//puts(s);
//scanf("%s",s);
int n=strlen(s);
for(int i=0;i<n;++i)
mt[s[i]]=i;
for(int i=0;i<n;++i)
mt[s[i]]=i;
cnt=0;
root=getNewNode();
for(int i=1;i<=p;++i)
{
gets(s);
//scanf("%s",s);
addWord(root,s,1);
}
}
void bfs(int p)
{
trie[p].fail=root;
queue<int>qt;
qt.push(p);
while(!qt.empty())
{
int y;
int x=qt.front();qt.pop();
for(int i=0;i<K;++i)
if(trie[x].next[i]!=-1)
{
qt.push(trie[x].next[i]);
if(x==root)
{trie[trie[x].next[i]].fail=root;continue;}
y=trie[x].fail;
while(y!=root&&trie[y].next[i]==-1)
y=trie[y].fail;
if(trie[y].next[i]!=-1)
trie[trie[x].next[i]].fail=trie[y].next[i];
else
trie[trie[x].next[i]].fail=root;
trie[trie[x].next[i]].v|=trie[trie[trie[x].next[i]].fail].v;
}
}
}
void makeTo(int n,int k)
{
for(int i=1;i<=n;++i)
for(int j=0;j<k;++j)
{
int p=i;
while(p!=root&&trie[p].next[j]==-1)
p=trie[p].fail;
if(trie[p].next[j]!=-1)
to[i][j]=trie[p].next[j];
else
to[i][j]=root;
}
};
int main()
{
//freopen("data.in","r",stdin);
int n,m,p;
scanf("%d %d %d ",&n,&m,&p);
init(p);
bfs(root);
makeTo(cnt,n);
dp[0][1]=BigInteger(1);
for(int i=0;i<m;++i)
for(int j=1;j<=cnt;++j)
{
for(int l=0;l<n;++l)
{
int r=to[j][l];
if(trie[r].v==1)
continue;
dp[i+1][r]=dp[i+1][r]+dp[i][j];
//cout<<(i+1)<<" "<<r<<endl;
//cout<<dp[i+1][r]<<endl;
}
}
BigInteger ans;
for(int j=0;j<=cnt;++j)
ans=ans+dp[m][j];
printf("%d",ans.bint[ans.len-1]);
for(int i=ans.len-2;i>=0;--i)
printf("%09d",ans.bint[i]);
printf("\n");
return 0;
}