【AC自动机+DP】 hdu3691 DNA repair

来源:互联网 发布:全钢网络地板 编辑:程序博客网 时间:2024/06/08 00:28

DNA repair

题目:http://poj.org/problem?id=3691

题意:就是给定N个病毒串,然后给定一个主串,然后求出修改主串多少次使得该串不包含病毒串。

题解:AC自动机+DP。首先是AC自动机的空指针要修改下,不能为空,也需要指向字典树里面的结点,为了之后在字典树上DP,然后建立fail指针。

dp(i,j)表示主串匹配到第i位时在自动机上的状态为j时的最少修改次数

代码:

#include<cstdio>#include<cstring>#include<queue>using namespace std;#define MAX 1005#define min(a,b) ((a)<(b)?(a):(b))int indx(char c){    switch(c)    {    case 'A':        return 0;    case 'G':        return 1;    case 'C':        return 2;    case 'T':        return 3;    }}struct node{    int next[4],fail;} head[MAX];int dp[MAX][MAX];bool danger[MAX];int cnt=1;void build(char *s,int idx){    int len=strlen(s),k;    for(int i=0; i<len; ++i)    {        k=indx(s[i]);        if(head[idx].next[k]==0)            head[idx].next[k]=(cnt++);        idx=head[idx].next[k];        if(danger[idx]) break;    }    danger[idx]=true;}void build_fail(int idx){    int now;    queue<int> q;    head[idx].fail=0;    q.push(idx);    for(; !q.empty();)    {        now=q.front();        q.pop();        for(int i=0; i<4; ++i)            if(head[now].next[i])            {                if(now==0) head[head[now].next[i]].fail=0;                else       head[head[now].next[i]].fail=head[head[now].fail].next[i];                if(danger[head[head[now].next[i]].fail])                    danger[head[now].next[i]]=true;//如果fail节点是危险的,那么本节点也是危险的(重要)                q.push(head[now].next[i]);            }            else            {                if(now==0) head[now].next[i]=0;                else       head[now].next[i]=head[head[now].fail].next[i];            }    }}int main(){    int n;    char s[MAX];    for(int cas=1; scanf("%d",&n),n;)    {        cnt=1;        memset(head,0,sizeof(head));        memset(danger,false,sizeof(danger));        for(; n--;)        {            scanf("%s",s);            build(s,0);        }        build_fail(0);        scanf("%s",s);        int w,len=strlen(s);        for(int i=0;i<=len;++i)            for(int j=0;j<=cnt;++j)                dp[i][j]=0xfffff;        dp[0][0]=0;        for(int i=1; i<=len; ++i)        {            w=indx(s[i-1]);            for(int j=0; j<cnt; ++j)                for(int k=0; k<4; ++k)                {                    int idx=head[j].next[k];                    if(danger[idx]) continue;                    dp[i][idx]=min(dp[i][idx],dp[i-1][j]+(k!=w));                }        }        int ans=0xfffff;        for(int i=0; i<cnt; ++i)            if(!danger[i])                ans=min(ans,dp[len][i]);        if(ans==0xfffff) ans=-1;        printf("Case %d: %d\n",cas++,ans);    }    return 0;}
来源:http://blog.csdn.net/acm_ted

原创粉丝点击