POJ 3691 AC自动机上的dp

 题目大意:

给定一些不合理的DNA序列,再给一段较长的dna序列,问最少修改几次可以使序列中不存在任何不合理序列,不能找到修改方法输出-1

这里你修改某一个点的DNA可能会影响后面,我们不能单纯的找匹配数,因为你找到了你也不一定有方法改变它 

这里用DP来解决

判断到第i位dna , 之前dp值保存了前面dna所能到达的所有状态:

dp[i][j] 也就是用了前i个dna所到达的状态至少需要修改的值

从所有状态出发,经过AGCT4种情况到达下一个状态,只要下一个状态不为非法状态即可

过程中只要判断你走的AGCT4种情况是否和当前字符相同,相同说明不用做出改变,即+0 , 否则+1,不断进行更新

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <queue>
  4 #include <vector>
  5 #include <iostream>
  6 #include <algorithm>
  7 #include <map>
  8 using namespace std;
  9 #define clr(x) memset(x , 0 , sizeof(x))
 10 #define set(x) memset(x , -1 , sizeof(x))
 11 typedef long long LL ;
 12 
 13 const int CHAR_SIZE = 4;
 14 const int MAX_SIZE = 1005;
 15 const int M = 10000 ;
 16 int n,m,p;
 17 int mp[256];
 18 
 19 struct AC_Machine{
 20     int ch[MAX_SIZE][CHAR_SIZE] , val[MAX_SIZE] , fail[MAX_SIZE];
 21     int sz;
 22 
 23     void init(){
 24         sz = 1;
 25         clr(ch[0]) , clr(val);
 26     }
 27 
 28     void insert(char *s){
 29         int n = strlen(s);
 30         int u=0 ;
 31         for(int i=0 ; i<n ; i++){
 32             int c = mp[s[i]];
 33             if(!ch[u][c]){
 34                 clr(ch[sz]);
 35                 val[sz] = 0;
 36                 ch[u][c] = sz++;
 37             }
 38             u = ch[u][c];
 39         }
 40         val[u] = 1;
 41     }
 42 
 43     void get_fail(){
 44         queue<int> Q;
 45         fail[0] = 0;
 46         for(int c=0 ; c<CHAR_SIZE ; c++){
 47             int u = ch[0][c];
 48             if(u){Q.push(u);fail[u]=0;}
 49         }
 50         while(!Q.empty()){
 51             int r = Q.front();
 52             Q.pop();
 53             val[r] |= val[fail[r]];
 54             for(int c=0 ; c<CHAR_SIZE ; c++){
 55                 int u = ch[r][c];
 56                 if(!u){ch[r][c] = ch[fail[r]][c]; continue;}
 57                 fail[u] = ch[fail[r]][c];
 58                 Q.push(u);
 59             }
 60         }
 61     }
 62 }ac;
 63 
 64 char str[1005];
 65 int f[1005][MAX_SIZE];
 66 int solve()
 67 {
 68     memset(f , 0x3f , sizeof(f));
 69     f[0][0] = 0;
 70     int len = strlen(str) , ret=0x3f3f3f3f;
 71     for(int i=1 ; i<=len ; i++){
 72         int v = mp[str[i-1]];
 73         for(int j=0 ; j<ac.sz ; j++){
 74             for(int k=0 ; k<CHAR_SIZE ; k++){
 75                 if(!ac.val[ac.ch[j][k]]){
 76                     f[i][ac.ch[j][k]] = min(f[i-1][j]+(v==k?0:1) , f[i][ac.ch[j][k]]);
 77                 }
 78             }
 79         }
 80     }
 81     for(int i=0 ; i<ac.sz ; i++){
 82         ret = min(ret , f[len][i]);
 83     }
 84     if(ret == 0x3f3f3f3f) return -1;
 85     else return ret;
 86 }
 87 
 88 int main()
 89 {
 90    // freopen("in.txt" , "r" , stdin);
 91    // freopen("out.txt" , "w" , stdout);
 92     mp['A'] = 0 , mp['G'] = 1 , mp['C'] = 2 , mp['T'] = 3;
 93     int cas = 0;
 94     while(scanf("%d" , &n),n){
 95         ac.init();
 96         for(int i=1 ; i<=n ; i++){
 97             scanf("%s" , str);
 98             ac.insert(str);
 99         }
100         ac.get_fail();
101         scanf("%s" , str);
102         printf("Case %d: " , ++cas);
103         printf("%d
" , solve());
104     }
105     return 0;
106 }
原文地址:https://www.cnblogs.com/CSU3901130321/p/4738186.html