HDU 2457DNA repair

来源:互联网 发布:淘宝大魔王是真是假 编辑:程序博客网 时间:2024/06/05 13:37

给定n个模式串,一个目标串,求目标串修改最少多少次可以使其不包含任何模式串。用二维dp来求,主要是要构建出DFA,具体看之前的的poj2778里的链接。然后就是判断转移时是否需要+1,和利用end数组判断当前是否可以转移。代码如下

#include<stdio.h>#include<iostream>#include<string.h>#include<algorithm>#include<queue>using namespace std;const int INF=1e9;const int MOD=20090717;int a[110];int dp[1010][1010];char str[1010];struct Tree{int next[1200][5],end[1100],fail[1100];int L,root;int newnode(){for(int i=0;i<4;i++){next[L][i]=-1;}end[L++]=0;return L-1;}void init(){L=0;root=newnode();}int getch(char ch){if(ch=='A') return 0;else if(ch=='G') return 1;else if(ch=='C') return 2;else if(ch=='T') return 3;}void insert(char *s){int len=strlen(s);int p=root;for(int i=0;i<len;i++){int id=getch(s[i]);if(next[p][id]==-1){next[p][id]=newnode();}p=next[p][id];}end[p]++;}void build(){queue<int>q;int p=root;fail[root]=root;for(int i=0;i<4;i++){if(next[p][i]==-1){next[p][i]=root;}else{fail[next[p][i]]=root;q.push(next[p][i]);}}while(!q.empty()){p=q.front();q.pop();if(end[fail[p]]) end[p]=1;  for(int i=0;i<4;i++){if(next[p][i]==-1){next[p][i]=next[fail[p]][i];}else{fail[next[p][i]]=next[fail[p]][i];q.push(next[p][i]);}}}}void query(char *s){int len=strlen(s);int p=root,ans=0;for(int i=0;i<len;i++){int id=s[i]-'a';p=next[p][id];int temp=p;while(temp!=root){if(end[temp]){ans+=end[temp];end[temp]=0;}temp=fail[temp];}}}void debug()    {        for(int i = 0;i < L;i++)        {            printf("id = %3d,fail = %3d,end = %3d,chi = [",i,fail[i],end[i]);            for(int j = 0;j < 26;j++)                printf("%2d",next[i][j]);            printf("]\n");        }    }    void solve()    {    int len=strlen(str);    for(int i=0;i<=len;i++)    {    for(int j=0;j<L;j++)    {    dp[i][j]=INF;    }    }    dp[0][0]=0;    for(int i=0;i<len;i++)    {    for(int j=0;j<L;j++)    {    //printf("!%d %d\n",i,j);    for(int k=0;k<4;k++)    {    int id=getch(str[i]);    int nextj=next[j][k];    //printf("%d %d %d %d %d %d\n",k,id,nextj,end[nextj],dp[i][j],dp[i+1][j]);    if(end[nextj]) continue;    int tmp;    if(id==k) tmp=dp[i][j];    else tmp=dp[i][j]+1;    dp[i+1][nextj]=min(dp[i+1][nextj],tmp);     }    }    }    int ans=INF;    for(int i=0;i<L;i++)    ans=min(ans,dp[len][i]);    if(ans==INF) printf("-1\n");    else printf("%d\n",ans);    }};Tree ac;char s[22];int main(){int cas=1;int n;while(~scanf("%d",&n)){if(n==0) break;ac.init();for(int i=0;i<n;i++){scanf("%s",s);ac.insert(s);}scanf("%s",str);ac.build();printf("Case %d: ",cas++);ac.solve();}}

0 0