zoukankan      html  css  js  c++  java
  • 【POJ3691】 DNA repair (AC自动机+DP)

    DNA repair
    Time Limit: 2000MS Memory Limit: 65536KB 64bit IO Format: %I64d & %I64u

    Description

    Biologists finally invent techniques of repairing DNA that contains segments causing kinds of inherited diseases. For the sake of simplicity, a DNA is represented as a string containing characters 'A', 'G' , 'C' and 'T'. The repairing techniques are simply to change some characters to eliminate all segments causing diseases. For example, we can repair a DNA "AAGCAG" to "AGGCAC" to eliminate the initial causing disease segments "AAG", "AGC" and "CAG" by changing two characters. Note that the repaired DNA can still contain only characters 'A', 'G', 'C' and 'T'.

    You are to help the biologists to repair a DNA by changing least number of characters.

    Input

    The input consists of multiple test cases. Each test case starts with a line containing one integers N (1 ≤ N ≤ 50), which is the number of DNA segments causing inherited diseases. 
    The following N lines gives N non-empty strings of length not greater than 20 containing only characters in "AGCT", which are the DNA segments causing inherited disease. 
    The last line of the test case is a non-empty string of length not greater than 1000 containing only characters in "AGCT", which is the DNA to be repaired.

    The last test case is followed by a line containing one zeros.

    Output

    For each test case, print a line containing the test case number( beginning with 1) followed by the 
    number of characters which need to be changed. If it's impossible to repair the given DNA, print -1.

    Sample Input

    2
    AAA
    AAG
    AAAG    
    2
    A
    TG
    TGAATG
    4
    A
    G
    C
    T
    AGT
    0

    Sample Output

    Case 1: 1
    Case 2: 4
    Case 3: -1
     
    【题意】
      已知一个DNA串和一些病毒DNA序列,求出最少改变DNA串中多少个字符,能使得串中不包含任意一个病毒序列。
     

    【分析】

      建AC自动机然后DP,不要走到有标记的点即可。

     代码如下:

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 #include<queue>
      7 using namespace std;
      8 #define Maxn 3010
      9 #define Maxl 1010
     10 #define INF 0xfffffff
     11 
     12 int n;
     13 char s[20];
     14 char ss[Maxl];
     15 
     16 struct node
     17 {
     18     int cnt,fail;
     19     bool mark;
     20     int son[5];
     21 }t[Maxn];int tot;//=0;
     22 
     23 void upd(int x)
     24 {
     25     t[x].cnt=1;t[x].mark=0;
     26     memset(t[x].son,0,sizeof(t[x].son));
     27 }
     28 
     29 int mymin(int x,int y) {return x<y?x:y;}
     30 
     31 void read_trie()
     32 {
     33     scanf("%s",s+1);
     34     int len=strlen(s+1);
     35     int now=0;
     36     for(int i=1;i<=len;i++)
     37     {
     38         int ind=s[i]-'A'+1;
     39         if(ind==3) ind=2;
     40         else if(ind==7) ind=3;
     41         else if(ind==20) ind=4;
     42         if(!t[now].son[ind]) 
     43         {
     44             t[now].son[ind]=++tot;
     45             upd(tot);
     46         }
     47         now=t[now].son[ind];
     48         if(i==len) t[now].mark=1;
     49     }
     50 }
     51 
     52 queue<int > q;
     53 // bool inq[Maxn];
     54 void build_AC()
     55 {
     56     while(!q.empty()) q.pop();
     57     q.push(0);//inq[0]=1;
     58     while(!q.empty())
     59     {
     60         int x=q.front();q.pop();
     61         for(int i=1;i<=4;i++) 
     62         {
     63             if(t[x].son[i])
     64             {
     65                 t[t[x].son[i]].fail=x?t[t[x].fail].son[i]:0;
     66                 q.push(t[x].son[i]);
     67             }
     68             else t[x].son[i]=t[t[x].fail].son[i];
     69             if(t[t[x].fail].mark) t[x].mark=1;
     70         }
     71     }
     72 }
     73 
     74 int f[Maxn][Maxl];
     75 void dp()
     76 {
     77     scanf("%s",ss+1);
     78     int len=strlen(ss+1);
     79     for(int i=1;i<=len;i++)
     80     {
     81         if(ss[i]=='C') ss[i]='B';
     82         else if(ss[i]=='G') ss[i]='C';
     83         else if(ss[i]=='T') ss[i]='D';
     84     }
     85     memset(f,63,sizeof(f));
     86     f[0][0]=0;
     87     for(int i=1;i<=len;i++)
     88      for(int j=0;j<=tot;j++) if(f[i-1][j]<INF)
     89      {
     90          for(int k=1;k<=4;k++) if(!t[t[j].son[k]].mark)
     91          {
     92              if(ss[i]-'A'+1==k) 
     93               f[i][t[j].son[k]]=mymin(f[i][t[j].son[k]],f[i-1][j]);
     94              else f[i][t[j].son[k]]=mymin(f[i][t[j].son[k]],f[i-1][j]+1);
     95          }
     96      }
     97     int ans=INF;
     98     for(int i=0;i<=tot;i++) ans=mymin(f[len][i],ans);
     99     if(ans<=len) printf("%d
    ",ans);
    100     else printf("-1
    ");
    101 }
    102 
    103 void init()
    104 {
    105     tot=0;
    106     upd(0);
    107     for(int i=1;i<=n;i++)
    108     {
    109         read_trie();
    110     }
    111     build_AC();
    112 }
    113 
    114 int main()
    115 {
    116     int kase=0;
    117     while(1)
    118     {
    119         scanf("%d",&n);
    120         if(n==0) break;
    121         init();
    122         printf("Case %d: ",++kase);
    123         dp();
    124     }
    125     return 0;
    126 }
    [POJ3691]

    2016-07-11 10:06:17

     

  • 相关阅读:
    cnblogs 博客园下载工具
    SQL 排序规则 CodeProject
    SQL 排序规则问题
    Datatbel和 string之间的相互转换
    C#三步实现标准事件处理程序
    利用C#来做ASP.NET的登陆页面
    C#用panel实现子窗体的切换
    C#中split分隔字符串的应用
    C#.NET 用程序画图,曲线图
    C#中消息的工作流程
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/5659327.html
Copyright © 2011-2022 走看看