首页 > 代码库 > [AC自动机+dp] hdu 2457 DNA repair

[AC自动机+dp] hdu 2457 DNA repair

题意:

给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;
}


[AC自动机+dp] hdu 2457 DNA repair