http://poj.org/problem?id=2778
AC自动机 + 矩阵连乘
代码:
#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=100000; const LL LMOD=100000; const int N=1005; const int M=1005; const int K=4; const int MATRIXN=5; const int MATRIXM=115; const int MATRIXH=115; 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]; LL ma[MATRIXN][MATRIXM],mb[MATRIXM][MATRIXH],mc[MATRIXM][MATRIXH]; 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[s[i]-'A']==-1) trie[p].next[s[i]-'A']=getNewNode(); p=trie[p].next[s[i]-'A']; } (trie[p].v)=k; } void init(int n) { cnt=0; root=getNewNode(); for(int i=0;i<4;++i) { s[0]='A'+i;s[1]='\0'; addWord(root,s,0); } while(n--) { gets(s); for(int i=0;s[i]!='\0';++i) { if(s[i]=='C') s[i]='B'; else if(s[i]=='G') s[i]='C'; else if(s[i]=='T') s[i]='D'; } 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; } } } void makeMatrix(LL a[][MATRIXM],int n) { for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) a[i][j]=0; for(int i=1;i<=n;++i) for(int j=0;j<4;++j) {//cout<<i<<endl; int p=i; int q=0; while(p!=root&&trie[p].next[j]==-1) p=trie[p].fail; if(trie[p].next[j]!=-1) q=trie[p].next[j]; int w=q; bool flag=true; while(w!=root) { if(trie[w].v>0) {flag=false;break;} w=trie[w].fail; } if(trie[w].v>0) flag=false; if(flag==true) a[i][q]=1; } } void matrixMul(LL a[][MATRIXM],LL b[][MATRIXM],int n,int m,int h) { for(int i=1;i<=n;++i) for(int j=1;j<=h;++j) { LL tmp=0; for(int l=1;l<=m;++l) tmp=(tmp+a[i][l]*b[l][j])%LMOD; mc[i][j]=tmp; } for(int i=1;i<=n;++i) for(int j=1;j<=h;++j) a[i][j]=mc[i][j]; } int main() { //freopen("data.in","r",stdin); int n,m; while(scanf("%d %d ",&n,&m)!=EOF) { init(n); bfs(root); int MN=1,MM=cnt,MH=cnt; makeMatrix(mb,MM); memset(ma,0,sizeof(ma)); ma[1][1]=1; while(m>0) { if((m&1)==1) matrixMul(ma,mb,MN,MM,MH); matrixMul(mb,mb,MM,MM,MH); m=(m>>1); } LL ans=0; for(int i=1;i<=MN;++i) for(int j=1;j<=MM;++j) ans=(ans+ma[i][j])%LMOD; cout<<ans<<endl; } return 0; }