POJ 3691 DNA repair(AC自动机+dp)

来源:互联网 发布:省市地区数据库 编辑:程序博客网 时间:2024/04/30 12:02

这道题实质上是指母串的DFA上跑一遍,不经过危险结点,要想完整跑下来最少需要修改几个字符。

有一个细节就是孩子结点为空时可以建立虚拟结点,那样就可以直接访问下面的结点了,不用前驱结点每次都去寻找。

状态方程是ans[i][j.son]=min{ans[i][j.son],ans[i-1][j]+str[i-1]!=k};

////  main.cpp//  Richard////  Created by 邵金杰 on 16/9/5.//  Copyright © 2016年 邵金杰. All rights reserved.//#include<iostream>#include<cstdio>#include<cstring>#include<queue>#include<map>using namespace std;const int maxn=1000+100;const int inf=100000000;struct node{    node *child[4];    node *pre;    bool badnode;    void intial(){        memset(child,0,sizeof(child));        pre=NULL;        badnode=false;    }}tree[maxn];int n;char s[30],str[maxn];int ans[maxn][maxn];map<char,int> m;int ncount;void Insert(node *p,char *ss){    for(;*ss;ss++)    {        int idx=m[*ss];        if(p->child[idx]==NULL)        {            tree[ncount].intial();            p->child[idx]=tree+ncount;            ncount++;        }        p=p->child[idx];    }    p->badnode=true;}void BuildDFA(){    for(int i=0;i<4;i++)        tree[0].child[i]=tree+1;    tree[0].pre=NULL;    tree[1].pre=tree;    queue<node*> q;    q.push(tree+1);    while(!q.empty())    {        node *proot=q.front();q.pop();        for(int i=0;i<4;i++)        {            node *p=proot->child[i];            if(p==NULL)            {                if(proot==tree+1)                    proot->child[i]=tree+1;                else                    proot->child[i]=proot->pre->child[i];            }            else{                node *pre=proot->pre;                while(pre)                {                    if(pre->child[i])                    {                        p->pre=pre->child[i];                        if(p->pre->badnode)                            p->badnode=true;                        break;                    }                    else                        pre=pre->pre;                }                q.push(p);            }        }    }}int dp(char *ss){    int len=(int)strlen(ss);    for(int i=0;i<maxn;i++)        for(int j=0;j<maxn;j++)            ans[i][j]=inf;    ans[0][1]=0;    for(int i=1;i<=len;i++)    {        for(int j=1;j<ncount;j++)        {            for(int k=0;k<4;k++)            {                node *tmp=tree[j].child[k];                if(tmp->badnode) continue;                int next=(int)(tmp-tree);                ans[i][next]=min(ans[i][next],ans[i-1][j]+(m[ss[i-1]]!=k));            }        }    }    int result=inf;    for(int i=1;i<ncount;i++)        result=min(result,ans[len][i]);    if(result==inf) return -1;    else return result;}int main(){    m['A']=0;m['G']=1;m['C']=2;m['T']=3;    int cases=0;    while(scanf("%d",&n)&&n)    {        ncount=2;        tree[0].intial();        tree[1].intial();        for(int i=0;i<n;i++)        {            scanf("%s",s);            Insert(tree+1,s);        }        BuildDFA();        scanf("%s",str);        printf("Case %d: ",++cases);        printf("%d\n",dp(str));    }    return 0;}

0 0
原创粉丝点击