【poj3691-DNA repair】AC自动机+DP

题意:给n个病毒DNA序列,再给一个DNA序列,问该序列至少修改多少个碱基能不含任何病毒DNA。病毒DNA序列一共不超过1000,询问的DNA长度不超过1000。

题解:DP:d[l][p]表示询问到第l位、当前在AC自动机上的位置为p时的最少修改数,用d[l][p]推d[l+1][x]。本来打的是递归,结果递归死循环了。。于是改成递推了。

不想清楚的话递归真的好容易死掉TAT

  1 //poj3691
  2 #include<cstdio>
  3 #include<cstdlib>
  4 #include<cstring>
  5 #include<iostream>
  6 #include<queue>
  7 using namespace std;
  8 
  9 const int N=1100,INF=(int)1e9;
 10 int n,num,sl,ans,d[N][N];
 11 char s[N];
 12 struct node{
 13     int fail,fa,bk,son[5];
 14 }a[N];
 15 queue<int> q;
 16 
 17 int minn(int x,int y){return x<y ? x:y;}
 18 
 19 int idx(char c)
 20 {
 21     if(c=='A') return 1;
 22     if(c=='T') return 2;
 23     if(c=='C') return 3;
 24     if(c=='G') return 4;
 25 }
 26 
 27 void clear(int x)
 28 {
 29     a[x].bk=a[x].fail=a[x].fa=0;
 30     memset(a[x].son,0,sizeof(a[x].son));
 31 }
 32 
 33 void read_trie()
 34 {
 35     scanf("%s",s);
 36     int x=0,l=strlen(s);
 37     for(int i=0;i<l;i++)
 38     {
 39         int ind=idx(s[i]);
 40         if(!a[x].son[ind])
 41         {
 42             clear(++num);
 43             a[x].son[ind]=num;
 44             a[num].fa=x;
 45         }
 46         x=a[x].son[ind];
 47     }
 48     a[x].bk=1;
 49 }
 50 
 51 void buildAC()
 52 {
 53     while(!q.empty()) q.pop();
 54     for(int i=1;i<=4;i++)
 55         if(a[0].son[i]) q.push(a[0].son[i]);
 56     while(!q.empty())
 57     {
 58         int x=q.front();q.pop();
 59         int fail=a[x].fail;
 60         for(int i=1;i<=4;i++)
 61         {
 62             if(a[x].son[i])
 63             {
 64                 int y=a[x].son[i],z=a[fail].son[i];
 65                 a[y].fail=z;
 66                 a[y].bk|=a[z].bk;
 67                 q.push(y);
 68             }
 69             else a[x].son[i]=a[fail].son[i];
 70         }
 71     }
 72 }
 73 
 74 int main()
 75 {
 76     freopen("a.in","r",stdin);
 77     freopen("a.out","w",stdout);
 78     int T=0;
 79     while(1)
 80     {
 81         scanf("%d",&n);
 82         if(!n) return 0;
 83         num=0;
 84         clear(0);
 85         for(int i=1;i<=n;i++) read_trie();
 86         buildAC();
 87         scanf("%s",s+1);
 88         sl=strlen(s+1);
 89         ans=INF;
 90         memset(d,63,sizeof(d));
 91         d[0][0]=0;
 92         for(int i=0;i<sl;i++)
 93         {
 94             for(int j=0;j<=num;j++)//在AC自动机上的位置
 95             {
 96                 if(d[i][j]<INF)
 97                 {
 98                     int ind=idx(s[i+1]);
 99                     int x=a[j].son[ind];
100                     for(int k=1;k<=4;k++)
101                     {
102                         int y=a[j].son[k];
103                         if(a[y].bk || x==y) continue;
104                         d[i+1][y]=minn(d[i+1][y],d[i][j]+1);
105                     }
106                     if(a[x].bk==0) 
107                         d[i+1][x]=minn(d[i+1][x],d[i][j]);
108                 }
109             }
110         }
111         for(int i=0;i<=num;i++) ans=minn(ans,d[sl][i]);
112         if(ans<INF) printf("Case %d: %d\n",++T,ans);
113         else printf("Case %d: -1\n",++T);
114     }
115     return 0;
116 }

 

posted @ 2016-07-18 10:55  拦路雨偏似雪花  阅读(309)  评论(0编辑  收藏  举报