直接从root遍历扩展DP,当扩展到的字母和字符串字母相同时,不用修改,不同时,要求修改加1
注意不要扩展危险结点。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <climits> #include <string.h> #include <queue> #include <cmath> #include <map> #include <vector> #define LL __int64 using namespace std; const int Maxn=1010; const int dictsize=4; const int root=0; const int inf=(1<<30); int ids['Z']; int fail[Maxn],trie[Maxn][dictsize]; bool tag[Maxn]; int head,tail,tot; int que[Maxn]; char str[Maxn]; int n; int dp[Maxn][Maxn]; void Insert_trie(){ int p=0,i=0,index; while(str[i]){ index=ids[str[i]]; if(trie[p][index]==-1) trie[p][index]=++tot; p=trie[p][index]; i++; } tag[p]=true; } void build_ac(){ head=tail=0; que[tail++]=root; while(head!=tail){ int tmp=que[head++]; int p=-1; for(int i=0;i<dictsize;i++){ if(trie[tmp][i]!=-1){ if(tmp==root) fail[trie[tmp][i]]=root; else{ p=fail[tmp]; while(p!=-1){ if(trie[p][i]!=-1){ fail[trie[tmp][i]]=trie[p][i]; break; } p=fail[p]; } if(p==-1) fail[trie[tmp][i]]=root; } if(tag[fail[trie[tmp][i]]]) tag[trie[tmp][i]]=true; que[tail++]=trie[tmp][i]; } else{ //trie[tmp][i]==-1 if(tmp==root) trie[tmp][i]=root; else{ p=fail[tmp]; while(p!=-1){ if(trie[p][i]!=-1){ trie[tmp][i]=trie[p][i]; break; } p=fail[p]; } if(p==-1) trie[tmp][i]=root; } } } } } int main(){ int T=0; ids['A']=0,ids['C']=1,ids['G']=2,ids['T']=3; while(scanf("%d",&n)&&n){ head=tail=tot=0; memset(fail,-1,sizeof(fail)); memset(trie,-1,sizeof(trie)); memset(tag,false,sizeof(tag)); for(int i=0;i<n;i++){ scanf("%s",str); Insert_trie(); } scanf("%s",str+1); build_ac(); int len=strlen(str+1); memset(dp,-1,sizeof(dp)); dp[0][0]=0; int son; for(int j=0;j<len;j++){ for(int i=0;i<=tot;i++){ if(dp[i][j]>=0){ for(int k=0;k<dictsize;k++){ if(!tag[trie[i][k]]){ son=trie[i][k]; if(k==ids[str[j+1]]){ if(dp[son][j+1]==-1){ dp[son][j+1]=dp[i][j]; } else{ dp[son][j+1]=min(dp[i][j],dp[son][j+1]); } } else{ if(dp[son][j+1]==-1){ dp[son][j+1]=dp[i][j]+1; } else{ dp[son][j+1]=min(dp[i][j]+1,dp[son][j+1]); } } } } } } } int ans=inf; for(int i=0;i<=tot;i++){ if(dp[i][len]!=-1){ ans=min(ans,dp[i][len]); } } printf("Case %d: %d ",++T,ans==inf?-1:ans); } return 0; }