HDU 2457 DNA repair(AC自动机+DP)

来源:互联网 发布:剑侠情缘手游数据互通 编辑:程序博客网 时间:2024/06/16 00:09

HDU 2457 DNA repair(AC自动机+DP)

http://acm.hdu.edu.cn/showproblem.php?pid=2457

题意:

        给你N个模板串,并且给你一个文本串,现在问你这个文本串最少需要改变几个字符才能使得它不包含任何模板串.(以上字符只由A,T,G,C构成).

分析:

        本题初看确实不知道怎么做,和之前做的题目都不一样.

        现在我们令dp[i][j]=x表示当前在自动机的i号节点,且走了长为j的路了,且过程中都不经过单词节点的情况下,与文本串的前j个字符不同点最少有x.(仔细体会dp[i][j]的定义).

        初值dp[i][j]=-1,dp[0][0]=0.

        dp[i][j] = min( dp[k][j-1] + v ) 从k可以走到i,且i和k都是非后缀单词.

        设从k走到i的那条边的字符为x,如果x==s[j-1],那么v=0.否则v=1.

AC代码:1A


#include<iostream>#include<queue>#include<map>#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#include<string>using namespace std;const int maxnode=1000+20;const int sigma_size=4;//后面读入int n,m;int len;char str[maxnode];struct AC_Automata{    int ch[maxnode][sigma_size];    int match[maxnode];//单词的结束结点记录这个单词的权值    int f[maxnode];    int sz;    int dp[maxnode][maxnode];    map<char,int>mp;    char signum[4];    void init()    {        sz=1;        memset(ch[0],0,sizeof(ch[0]));        match[0]=f[0]=0;        mp['A']=0,signum[0]='A';        mp['T']=1,signum[1]='T';        mp['G']=2,signum[2]='G';        mp['C']=3,signum[3]='C';    }    void insert(char *s)//v表示第几个单词    {        int n=strlen(s),u=0;        for(int i=0;i<n;i++)        {            int id=mp[s[i]];            if(ch[u][id]==0)            {                ch[u][id]=sz;                memset(ch[sz],0,sizeof(ch[sz]));                match[sz++]=0;            }            u=ch[u][id];        }        match[u]|=1;    }    void getFail()    {        f[0]=0;        queue<int> q;        for(int i=0;i<sigma_size;i++)        {            int u=ch[0][i];            if(u)            {                f[u]=0;                q.push(u);            }        }        while(!q.empty())        {            int r=q.front();q.pop();            for(int i=0;i<sigma_size;i++)            {                int u=ch[r][i];                if(!u){ ch[r][i]=ch[f[r]][i]; continue; }                q.push(u);                int v=f[r];                while(v && ch[v][i]==0) v=f[v];                f[u]=ch[v][i];                match[u] |= match[f[u]];            }        }    }    int  solve()    {    int ans=-1;    for(int i=0;i<sz;i++){for(int j=0;j<=len;j++){dp[i][j]=-1;}}dp[0][0]=0;for(int lens=0;lens<len;lens++){for(int i=0;i<sz;i++){if(match[i]==0&&dp[i][lens]!=-1){for(int j=0;j<sigma_size;j++){if(match[ch[i][j]]==0){int k=ch[i][j];int v=(str[lens]==signum[j])?0:1;//当前结点是否需要修改if(dp[k][lens+1]!=-1){dp[k][lens+1]=min(dp[i][lens]+v,dp[k][lens+1]);}else{dp[k][lens+1]=dp[i][lens]+v;}if(lens+1==len){if(ans!=-1){ans=min(ans,dp[k][len]);}elseans=dp[k][len];}}}}}}return ans;    }};AC_Automata ac;int main(){int kase=0;    while(~scanf("%d",&n)&&n){ac.init();for(int i=0;i<n;i++){scanf("%s",str);ac.insert(str);}scanf("%s",str);len=strlen(str);ac.getFail(); printf("Case %d: %d\n",++kase,ac.solve());}    return 0;}


原创粉丝点击