DNA repair HDU - 2457(ac自动机)

DNA repair

 HDU - 2457

题意:有些DNA序列是致病的,给你以个长DNA序列,问最少需要修改多少次使得其不含致病序列。

好多题解说的不清不楚的。。。最关键的地方往往没说清楚。。。

首先是进行了一步转换,将其理解为在建好的Trie图上走len(序列长度)步,走的路不能包含致病序列。

然后就变成了一个dp,d[i][j]表示第i步走到j节点最少需要修改几次。那么要看所有能走到j节点的点,如果和s[i-1]相同,就不用修改,如果不同,修改次数加一,取较小的。

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 #define CLR(m,a) memset(m,a,sizeof(m))
  4 const int inf=0x3f3f3f3f;
  5 const int maxnode=50*20+10;
  6 const int sigma=4;
  7 
  8 struct AC{
  9     int ch[maxnode][sigma],f[maxnode];
 10     int match[maxnode];
 11     int sz;
 12     int mp[128];
 13 
 14     void init(){
 15         CLR(match,0);
 16         mp['A']=0;mp['G']=1;mp['C']=2;mp['T']=3;
 17         CLR(ch[0],0);
 18         sz=1;
 19     }
 20     void inser(char *s){
 21         int u=0,n=strlen(s);
 22         for(int i=0;i<n;i++){
 23             int c=mp[s[i]];
 24             if(!ch[u][c]){
 25                 CLR(ch[sz],0);
 26                 ch[u][c]=sz++;
 27             }
 28             u=ch[u][c];
 29         }
 30         match[u]=1;
 31     }
 32     void getfail(){
 33         queue<int> q;
 34         f[0]=0;
 35         match[0]=0;
 36         for(int c=0;c<sigma;c++){
 37             int u=ch[0][c];
 38             if(u){
 39                 q.push(u);
 40                 f[u]=0;
 41             }
 42         }
 43         while(!q.empty()){
 44             int r=q.front();
 45             q.pop();
 46             for(int c=0;c<sigma;c++){
 47                 int u=ch[r][c];
 48                 if(!u){
 49                     ch[r][c]=ch[f[r]][c];
 50                     continue;
 51                 }
 52                 q.push(u);
 53                 int v=f[r];
 54                 while(v&&!ch[v][c]) v=f[v];
 55                 f[u]=ch[v][c];
 56                 match[u]|=match[f[u]];
 57             }
 58         }
 59     }
 60 };
 61 AC ac;
 62 char s[maxnode];
 63 int len;
 64 int dp[maxnode][maxnode];
 65 
 66 void DP(){
 67     CLR(dp,inf);
 68     dp[0][0]=0;
 69     for(int i=1;i<=len;i++){
 70         for(int j=0;j<ac.sz;j++){
 71             if(ac.match[j]) continue;
 72             for(int c=0;c<sigma;c++){
 73                 if(ac.match[ac.ch[j][c]]) continue;
 74                 dp[i][ac.ch[j][c]]=min(dp[i][ac.ch[j][c]],dp[i-1][j]+(ac.mp[s[i-1]]!=c));
 75             }
 76         }
 77     }
 78 }
 79 int main(){
 80     int n;
 81     int kase=0;
 82     while(scanf("%d",&n)!=EOF&&n){
 83         ac.init();
 84         for(int i=0;i<n;i++){
 85             scanf("%s",s);
 86             ac.inser(s);
 87         }
 88         ac.getfail();
 89         scanf("%s",s);
 90         len=strlen(s);
 91         DP();
 92         int ans=inf;
 93         for(int i=0;i<ac.sz;i++)if(!ac.match[i]){
 94             ans=min(dp[len][i],ans);
 95         }
 96         if(ans==inf) ans=-1;
 97         printf("Case %d: %d\n",++kase,ans);
 98     }
 99     return 0;
100 }
View Code

 

posted @ 2017-08-18 10:54  yijiull  阅读(299)  评论(0编辑  收藏  举报