题意:
给N个单词,再给一个串str (只含A、G、C、T)
问对于str要至少修改几个字符能不含有N个单词
思路:
建立trie图,做自动机dp
dp[i][j] 代表走过str的i个字母在j节点至少需要修改几个字符
trie *p=node[j]->next[k]; if(p->mark) continue; //不可达 dp[i][p->id]=min(dp[i][p->id],dp[i-1][j]+(getid(fuck[i])!=k));
就是第i步从节点j走到对应的k,如果k不是这步的字母就修改,取最小值。
最后遍历长度为len时每个节点的情况,取最小值。
代码:
#include"cstdlib" #include"cstdio" #include"cstring" #include"cmath" #include"queue" #include"algorithm" #include"iostream" #include"map" #include"string" #define inf 9999999 using namespace std; int triecont; struct trie { int mark,id; trie *next[5],*fail; trie() { memset(next,0,sizeof(next)); fail=NULL; mark=id=0; } }; trie *root,*node[1234]; int getid(char x) { if(x=='A') return 0; else if(x=='C') return 1; else if(x=='G') return 2; return 3; } void init(char *v) { trie *p=root; for(int i=0;v[i];i++) { int tep=getid(v[i]); if(p->next[tep]==NULL) { p->next[tep]=new trie(); node[triecont]=p->next[tep]; p->next[tep]->id=triecont++; } p=p->next[tep]; } p->mark=1; } void getac() { queue<trie*>q; q.push(root); while(!q.empty()) { trie *p=q.front(); q.pop(); for(int i=0;i<4;i++) { if(p->next[i]==NULL) { if(p==root) p->next[i]=root; else p->next[i]=p->fail->next[i]; } else { if(p==root) p->next[i]->fail=root; else p->next[i]->fail=p->fail->next[i]; q.push(p->next[i]); trie *tep=p; while(tep!=root && tep->mark!=1) tep=tep->fail; p->mark=tep->mark; } } } } int dp[1234][1234]; char fuck[1234]; int main() { int n; int cas=1; while(scanf("%d",&n),n) { triecont=0; root=new trie(); node[triecont]=root; root->id=triecont++; while(n--) { char x[33]; scanf("%s",x); init(x); } getac(); //for(int i=0;i<triecont;i++) printf("%d:%d\n",i,node[i]->mark); scanf("%s",fuck+1); int len=strlen(fuck+1); for(int i=0;i<=len;i++) for(int j=0;j<triecont;j++) dp[i][j]=inf; dp[0][0]=0; for(int i=1;i<=len;i++) { for(int j=0;j<triecont;j++) { if(dp[i-1][j]==inf) continue; for(int k=0;k<4;k++) { trie *p=node[j]->next[k]; if(p->mark) continue; dp[i][p->id]=min(dp[i][p->id],dp[i-1][j]+(getid(fuck[i])!=k)); } } } int ans=inf; for(int i=0;i<triecont;i++) ans=min(ans,dp[len][i]); printf("Case %d: %d\n",cas++,ans==inf?-1:ans); } return 0; }
时间: 2024-10-10 04:06:20