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; }