zoukankan      html  css  js  c++  java
  • POJ 3691 DNA repair AC自动机 + DP

    题意:给你只包含‘A’,‘G’,‘T’,‘C’四个字母的n个模板串和1个文本串,问你文本串改变多少个字符就可以使得文本串中没有一个模板串

    解题思路:

    我们可以知道  dp[i][j] 为文本串到 第i 个字符  AC自动机状态为j的最少的变换次数(这里为什么要用AC自动机,因为end数组可以记录哪一个状态是结束的,而且处理以后可以知道那些后缀等于前缀--也就是不能到达,因为如果能够到达的话那么状态更新就会产生错误。),这样dp即可

    解题代码:

      1 // File Name: temp.cpp
      2 // Author: darkdream
      3 // Created Time: 2014年09月11日 星期四 15时18分4秒
      4 
      5 #include<vector>
      6 #include<list>
      7 #include<map>
      8 #include<set>
      9 #include<deque>
     10 #include<stack>
     11 #include<bitset>
     12 #include<algorithm>
     13 #include<functional>
     14 #include<numeric>
     15 #include<utility>
     16 #include<sstream>
     17 #include<iostream>
     18 #include<iomanip>
     19 #include<cstdio>
     20 #include<cmath>
     21 #include<cstdlib>
     22 #include<cstring>
     23 #include<ctime>
     24 #include<queue>
     25 #define LL long long
     26 #define maxn 1005
     27 
     28 using namespace std;
     29 int dp[maxn][maxn];   
     30 struct Trie
     31 {
     32     int next[maxn][4],fail[maxn],end[maxn];
     33     int root, L;
     34     int newnode()
     35     {
     36         memset(next[L],-1,sizeof(next[L]));
     37         end[L++] = 0 ;
     38         return L-1;
     39     }
     40     void init()
     41     {
     42         L = 0 ; 
     43         root = newnode();
     44     }
     45     void insert(int buf[],int len)
     46     {
     47         int now = root;
     48         for(int i = 0 ;i < len ;i ++)
     49         {
     50             if(next[now][buf[i]] ==  -1)
     51             {
     52                 next[now][buf[i]] = newnode();
     53             }
     54             now = next[now][buf[i]];
     55         }
     56         end[now] = 1;
     57     }
     58     void build()
     59     {
     60         queue<int> Q;
     61         fail[root] = root; 
     62         for(int i = 0;i < 4;i ++)
     63         {
     64             if(next[root][i] == -1)
     65             {
     66                 next[root][i] = root;  //指向root 是没有问题的,我们主要是通过end 数组对个数进行计数的。    
     67             }else{
     68                 fail[next[root][i]] = root;
     69                 Q.push(next[root][i]);
     70             }
     71         }
     72         while(!Q.empty())
     73         {
     74             int now = Q.front();
     75             Q.pop();
     76             for(int i = 0 ;i < 4;i ++)
     77             {
     78                 if(next[now][i] == -1)
     79                 {
     80                     next[now][i] =  next[fail[now]][i]; 
     81                 }
     82                 else{
     83                     fail[next[now][i]] = next[fail[now]][i];
     84                     if(end[next[fail[now]][i]] == 1)
     85                         end[next[now][i]] = 1;
     86                     Q.push(next[now][i]);
     87                 }
     88             }
     89         }
     90     }
     91     void query(int buf[],int len,int ca)
     92     {
     93         //end[3] = 1;
     94         memset(dp,2,sizeof(dp));
     95         dp[0][0] = 0; 
     96         for(int i = 0 ;i < len ;i ++)
     97         {
     98             for(int j = 0 ;j < L ;j ++ )    
     99             {
    100              if(dp[i][j] < len && end[j] != 1)
    101                for(int s = 0 ;s < 4;s ++)
    102                {
    103                  if(end[next[j][s]] != 1)
    104                  dp[i+1][next[j][s]] = min(dp[i+1][next[j][s]],dp[i][j] + (buf[i] == s?0:1));
    105                }
    106             }
    107         }
    108        int ans = dp[len][0];
    109        for(int i = 0 ;i < L ;i ++)
    110        {
    111            if(end[i] != 1)
    112            ans = min(dp[len][i],ans);
    113        }
    114        if(ans <= len)
    115        {
    116           printf("Case %d: %d
    ",ca,ans);
    117        }else{
    118           printf("Case %d: -1
    ",ca); 
    119        }
    120 
    121     }
    122 };
    123 char buf[3000];
    124 int  temp[3000];
    125 Trie ac;
    126 void change(int len)
    127 {
    128     for(int i = 0;i < len;i ++)
    129     {
    130        if(buf[i] == 'A')
    131        {
    132          temp[i] = 0 ; 
    133        }else if(buf[i] == 'T'){
    134          temp[i] = 1; 
    135        }else if(buf[i] == 'G')
    136        {
    137           temp[i] = 2; 
    138        }else if(buf[i] == 'C')
    139        {
    140           temp[i] = 3; 
    141        }
    142     }
    143 }
    144 int main(){
    145     int n;
    146     int ca= 0 ;
    147     //freopen("in","r",stdin);
    148     while(scanf("%d",&n) != EOF,n)
    149     {
    150         ca ++ ; 
    151         ac.init();
    152         int len = strlen(buf);
    153         for(int i =1 ;i <= n;i ++)
    154         {
    155           scanf("%s",buf);
    156           len = strlen(buf);
    157           change(len);
    158           ac.insert(temp,len);
    159         }
    160         ac.build();
    161         scanf("%s",buf);
    162         len = strlen(buf);
    163         change(len);
    164         ac.query(temp,len,ca);
    165     }
    166     return 0;
    167 }
    View Code
    没有梦想,何谈远方
  • 相关阅读:
    css小技巧: select的css控制
    js中不存在exit函数,程序的运行中断停止,可使用return
    转载: WebCore渲染之一:基础
    转载: WEB架构师成长系列索引
    js:<form></form>中有<a>按钮时不能跳转?
    小心得:前台与后台的数据传递
    php session和cookie使用说明
    css 字体使用
    转载: PHP引用(&)使用详解
    三层架构下的增删改查 荣
  • 原文地址:https://www.cnblogs.com/zyue/p/3973867.html
Copyright © 2011-2022 走看看