• Match:DNA repair(POJ 3691)


                    

                    基因修复

      题目大意:给定一些坏串,再给你一个字符串,要你修复这个字符串(AGTC随便换),使之不含任何坏串,求修复所需要的最小步数。

      这一题也是和之前的那个1625的思想是一样的,通过特殊的trie树找到所有的状态然后一个一个枚,具体状态转移的思想可以在1625那里看

      当然了这一题不是像1625那样求总的组合数,这一题也是DP,求的是最小值,那么我们也是一样,统计从合法状态中转移到任何一个状态最小值即可。

      状态转移方程dp[i+1][转移状态]=min(dp[i+1][转移状态],dp[i][当前状态]+s)(当转移状态对应的就是trie的节点,当节点对应的字符等于字符串当前位置的字符,则s为0,否则s为1。)

      1 #include <iostream>
      2 #include <algorithm>
      3 #include <functional>
      4 #include <string.h>
      5 #define MAX 1010
      6 
      7 using namespace std;
      8 
      9 struct node
     10 {
     11     int Num, If_End;
     12     struct node *Fail, *Next[4];
     13 }*root, Mem_Pool[MAX], *Queue[2 * MAX];
     14 
     15 static int sum_node, Hash_Table[256], dp[MAX][MAX];
     16 static char str[MAX], DNA[4] = { 'A', 'G', 'C', 'T' };
     17 
     18 struct node *create_new_node();
     19 int find_min(const int, const int);
     20 void put_DNA_into_hash(void);
     21 void insert(struct node *);
     22 void build_ac_automation(struct node *);
     23 
     24 int main(void)
     25 {
     26     int Disease_Segement_Sum, str_length, case_sum = 1;
     27 
     28     put_DNA_into_hash();
     29     while (~scanf("%d", &Disease_Segement_Sum))
     30     {
     31         if (Disease_Segement_Sum == 0)
     32             break;
     33         sum_node = 0;
     34         node *root = create_new_node();
     35         getchar();
     36         
     37         for (int i = 0; i < Disease_Segement_Sum; i++)
     38             insert(root);
     39         build_ac_automation(root);
     40 
     41         gets(str);
     42         str_length = strlen(str);
     43 
     44         for (int i = 0; i < str_length; i++)
     45         {
     46             fill(dp[i + 1], dp[i + 1] + sum_node, MAX + 1);
     47             for (int j = 0; j < sum_node; j++)
     48             {
     49                 if (Mem_Pool[j].If_End)
     50                     continue;
     51                 for (int k = 0; k < 4; k++)
     52                 {
     53                     int id = Mem_Pool[j].Next[k]->Num;
     54                     if (Mem_Pool[j].Next[k]->If_End)
     55                         continue;
     56                     else if (Hash_Table[str[i]] == k)
     57                         dp[i + 1][id] = find_min(dp[i + 1][id], dp[i][j]);
     58                     else
     59                         dp[i + 1][id] = find_min(dp[i + 1][id], dp[i][j] + 1);
     60                 }
     61             }
     62         }
     63         int ans = MAX + 1;
     64         for (int i = 0; i < sum_node; i++)
     65             ans = find_min(ans, dp[str_length][i]);
     66         if (ans != MAX + 1)
     67             printf("Case %d: %d
    ", case_sum++, ans);
     68         else
     69             printf("Case %d: -1
    ",case_sum++);
     70     }
     71     return EXIT_SUCCESS;
     72 }
     73 
     74 int find_min(const int x, const int y)
     75 {
     76     return x < y ? x : y;
     77 }
     78 
     79 struct node *create_new_node(void)
     80 {
     81     node *tmp = &Mem_Pool[sum_node];
     82     tmp->Fail = NULL;
     83     tmp->If_End = 0;
     84     memset(tmp->Next, 0, sizeof(struct node *) * 4);
     85     tmp->Num = sum_node++;
     86     return tmp;
     87 }
     88 
     89 void put_DNA_into_hash(void)
     90 {
     91     for (int i = 0; i<4; i++)
     92         Hash_Table[DNA[i]] = i;
     93 }
     94 
     95 void insert(struct node *root)
     96 {
     97     node *ptr = root;
     98     gets(str);
     99 
    100     for (int i = 0; str[i] != ''; i++)
    101     {
    102         int id = Hash_Table[str[i]];
    103         if (ptr->Next[id] == NULL)
    104             ptr->Next[id] = create_new_node();
    105         ptr = ptr->Next[id];
    106     }
    107     ptr->If_End = 1;
    108 }
    109 
    110 void build_ac_automation(struct node *root)
    111 {
    112     int head = 0, tail = 0;
    113     root->Fail = NULL;
    114     Queue[tail++] = root;
    115 
    116     while (head != tail)
    117     {
    118         node *out = Queue[head++];
    119         for (int i = 0; i < 4; i++)
    120         {
    121             if (out->Next[i] != NULL)
    122             {
    123                 if (out == root)
    124                     out->Next[i]->Fail = root;
    125                 else
    126                 {
    127                     out->Next[i]->Fail = out->Fail->Next[i];
    128                     if (out->Fail->Next[i]->If_End)
    129                         out->Next[i]->If_End = 1;
    130                 }
    131                 Queue[tail++] = out->Next[i];
    132             }
    133             else if (out == root)
    134                 out->Next[i] = root;
    135             else
    136                 out->Next[i] = out->Fail->Next[i];
    137         }
    138     }
    139 }

      

  • 相关阅读:
    url 路径的拼接
    java 实现导出Excel文件
    window 使用频率最高的快捷键
    jeesite 框架的简单应用
    一个软件开发者的解决问题的心得——善于利用蛛丝马迹
    在linux上安装dotnetcore
    c#多线程同步之EventWaitHandle使用
    sharepoint 2013 安装
    模板模式的应用
    正则表达式的应用
  • 原文地址:https://www.cnblogs.com/Philip-Tell-Truth/p/5191381.html
Copyright © 2020-2023  润新知