• 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 }
  • 相关阅读:
    JSP简单访问数据库
    解析数据存储MySQL
    学习SSH框架
    JavaWEB中读取配置信息
    Eclipse中将Java项目转换成Web项目的方法
    JavaWEB入门
    万能数据库连接类-Oracle、DB2 、Access 、Sql Server
    小米3 打开开发者选项
    coolpad 5879logcat不能输入日志解决办法
    实用开发之-oracle表回滚到一个指定时间的操作语句
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4738186.html
Copyright © 2020-2023  润新知