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\n", case_sum++, ans); 68 else 69 printf("Case %d: -1\n",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] != '\0'; 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 }