http://poj.org/problem?id=3691
AC自动机+DP
代码:
#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=1010; const int M=1010; const int K=4; 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]; int 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 n) { cnt=0; root=getNewNode(); for(int i=1;i<=n;++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); mt.insert(pair<char,int>('A',0)); mt.insert(pair<char,int>('C',1)); mt.insert(pair<char,int>('G',2)); mt.insert(pair<char,int>('T',3)); int n; int ca=0; while(scanf("%d ",&n)!=EOF,n) {++ca; init(n); bfs(root); makeTo(cnt,K); //gets(s); scanf("%s",s); int m=strlen(s); memset(dp,-1,sizeof(dp)); dp[0][1]=0; for(int i=0;i<m;++i) for(int j=1;j<=cnt;++j) if(dp[i][j]!=-1) { for(int w=0;w<K;++w) { int r=to[j][w]; if(trie[r].v==1) continue; int tmp=(w==mt[s[i]])?0:1; if(dp[i+1][r]==-1||dp[i+1][r]>dp[i][j]+tmp) dp[i+1][r]=dp[i][j]+tmp; //cout<<(i+1)<<" "<<r<<" "<<dp[i+1][r]<<endl; //cout<<dp[i+1][r]<<endl; } } int ans=-1; for(int j=1;j<=cnt;++j) if(dp[m][j]!=-1) if(ans==-1||dp[m][j]<ans) ans=dp[m][j]; printf("Case %d: %d\n",ca,ans); } return 0; }