题目链接:http://poj.org/problem?id=2778
http://poj.org/problem?id=1625
http://poj.org/problem?id=3691
AC自动机用于多字符串配匹问题,而此结构中存储的是一个前缀状态的集合,通过结点之间边(失败指针、后继指针)的联系,实现通过接受输入字符达到状态的转移。而状
态的转移通常可以和动态规划联系在一起。在这些题中恰好可以用其存储字符串的前缀及这些前缀的危险性状态,即每个节点可以代表一个前缀的状态,而通过接受输入字符达
到状态的改变。在AC自动机中转移的同时,消除重复的状态,达到状态的压缩表示的目的。子节点的状态可以从其父节点处得到,所在,动态规划过程中,只处理前一状态与
当前接收输入字符后的状态间的关系。
在建立AC自动机时,如果保证节点的后继中没有空指针,而指向其失败指针指向节点的同一后继节点,就构成了Trie图。
Code:2778
#include<stdio.h> #include<stdlib.h> #include<string.h> #define M 128 #define Mod 100000 typedef struct{ int c,fail; int nxt[4]; }Trie; Trie T[M]; int q[M]; int head,tail; int size; int m,n; int A[M][M],R[M][M]; char dna[16]; int Key(char c) { int r=4; switch(c){ case 'A':r--; case 'C':r--; case 'G':r--; case 'T':r--; } return r; } int NewTrie() { return ++size; } void Insert(char *p) { int a,cur=1; while(*p){ a=Key(*p++); if(!T[cur].nxt[a]) T[cur].nxt[a]=NewTrie(); cur=T[cur].nxt[a]; } T[cur].c++; } void ACAutomation() { int cur,pre,i; head=tail=0; q[tail++]=1; while(head^tail){ cur=q[head++]; for(i=0;i<4;i++){ if(!T[cur].nxt[i]) continue; if(cur==1) T[T[cur].nxt[i]].fail=1; else{ pre=T[cur].fail; while(pre&&!T[pre].nxt[i]) pre=T[pre].fail; T[T[cur].nxt[i]].fail=pre?T[pre].nxt[i]:1; if(pre&&T[T[pre].nxt[i]].c) T[T[cur].nxt[i]].c++; } q[tail++]=T[cur].nxt[i]; } } } void GetPreMatrix() { int i,j,k; for(i=1;i<=size;i++){ if(T[i].c) continue; for(j=0;j<4;j++){ if(T[i].nxt[j]&&!T[T[i].nxt[j]].c) A[i][T[i].nxt[j]]++; else if(!T[i].nxt[j]){ if(i==1) A[1][1]++; else{ k=i; while(!T[k].nxt[j]&&k!=1) k=T[k].fail; if(T[k].nxt[j]&&!T[T[k].nxt[j]].c) A[i][T[k].nxt[j]]++; else if(!T[k].nxt[j]&&k==1) A[i][1]++; } } } } } void MatrixMulti(int a[M][M],int b[M][M]) { int i,j,k; __int64 tmp; int c[M][M]={0}; for(i=1;i<=size;i++){ for(j=1;j<=size;j++){ for(k=1;k<=size;k++){ tmp=((__int64)a[i][k])*((__int64)b[k][j]); if(tmp>=Mod) tmp%=Mod; c[i][j]+=tmp; } } } for(i=1;i<=size;i++){ for(j=1;j<=size;j++) a[i][j]=c[i][j]; } } void GetResMatrix() { int i; for(i=1;i<=size;i++) R[i][i]=1; while(n){ if(n&1) MatrixMulti(R,A); MatrixMulti(A,A); n>>=1; } } int main() { int res; int i; scanf("%d%d",&m,&n); size=1; while(m--){ scanf("%s",dna); Insert(dna); } ACAutomation(); GetPreMatrix(); GetResMatrix(); for(i=1,res=0;i<=size;i++){ res+=R[1][i]; if(res>=Mod) res%=Mod; } printf("%d\n",res); return 0; }
Code:1625
void TrieGraph() { int i,cur; head=tail=0; for(i=0;i<n;i++){ if(T[1].son[i]){ T[T[1].son[i]].fail=1; q[tail++]=T[1].son[i]; }else T[1].son[i]=1; } while(head^tail){ cur=q[head++]; if(T[T[cur].fail].end) T[cur].end++; for(i=0;i<n;i++){ if(T[cur].son[i]){ T[T[cur].son[i]].fail=T[T[cur].fail].son[i]; q[tail++]=T[cur].son[i]; } else T[cur].son[i]=T[T[cur].fail].son[i]; } } }void DPWork() { int i,j,k; dp[0][1][0]=1; for(i=1;i<=m;i++){ for(j=1;j<=size;j++){ if(T[j].end) continue; for(k=0;k<n;k++){ if(T[T[j].son[k]].end) continue; Add(dp[i][T[j].son[k]],dp[i-1][j]); } } } for(i=1;i<=size;i++){ if(T[i].end) continue; Add(res,dp[m][i]); } }
Code:3691
void TrieDPWork() { int i,j,k,a; memset(dp,12,sizeof(dp)); Inf=res=dp[0][0]; a=Key(s[0]); if(!T[T[r].son[a]].end) dp[0][T[r].son[a]]=0; for(i=0;i<4;i++){ if(a!=i&&!T[T[r].son[i]].end) dp[0][T[r].son[i]]=1; } for(i=1;s[i];i++){ a=Key(s[i]); for(j=1;j<=size;j++){ if(~dp[i-1][j]){ if(!T[T[j].son[a]].end) dp[i][T[j].son[a]]=Min(dp[i][T[j].son[a]],dp[i-1][j]); for(k=0;k<4;k++){ if(a!=k&&!T[T[j].son[k]].end){ dp[i][T[j].son[k]]=Min(dp[i][T[j].son[k]],dp[i-1][j]+1); } } } } } k=i-1; for(i=1;i<=size;i++) res=Min(res,dp[k][i]); }