poj 3769DNArepair

/*2016.01.22
 *poj3769DNArepair.cpp
 * ac自动机+dp, 多模式匹配
 * 考虑存在这样的修改满足题意,则沿着修改后的字符串进行状态转移每一步都
 * 将到达安全的状态(不含病毒串为子串),满足最优子结构。假设:
 * c 为从状态from到to的字符,dp[i][to]表示第i步到达to状态最少需要改变的字符数,
 * 状态from 和 to 都要是安全的:
 * dp[i][to] = min(dp[i-1][from] + c != s[i], dp[i][to])
 */

  1 #include <cstdio>
  2 #include <map>
  3 #include <string.h>
  4 #include <algorithm>
  5 using namespace std;
  6
  7 const int MAX = 1010, SZ = 4;
  8 int dp[MAX], tmp[MAX], cur;
  9 map<char, int> c2n;
 10
 11 class node {
 12 public:
 13     int unsafe;
 14     node *next[SZ], *fail;
 15     void init(){
 16         memset(this, 0, sizeof(node));
 17     }
 18 }ac[MAX], *q[MAX], *rt;
 19
 20 void Insert(char *s){
 21     int i=0, idx;
 22     node *p=rt;
 23     for(i=0; s[i]; ++i){
 24         idx = c2n[s[i]];
 25         if(p->next[idx] == NULL){
 26             p->next[idx] = &ac[cur];
 27             ac[cur++].init();
 28         }
 29         p = p->next[idx];
 30     }
 31     p->unsafe = 1;
 32 }
 33 //v1:
 34 // void BuildAC(){
 35 //     int h = 1, t = 0, i;
 36 //     node *nd;
 37 //     q[0] = rt;
 38 //     rt->fail = NULL;
 39 //     while(t < h){
 40 //         for(i=0; i<SZ; ++i){
 41 //             if(q[t]->next[i] == NULL) continue;
 42 //             if(q[t] == rt) q[t]->next[i]->fail = rt;
 43 //             else {
 44 //                 nd = q[t]->fail;
 45 //                 while(nd != NULL && nd->next[i] == NULL) nd = nd->fail;
 46 //                 if(nd == NULL) q[t]->next[i]->fail = rt;
 47 //                 else {
 48 //                     q[t]->next[i]->fail = nd->next[i];
 49 //                     q[t]->next[i]->unsafe |= nd->next[i]->unsafe;
 50 //                 }
 51 //             }
 52 //             q[h++] = q[t]->next[i];
 53 //         }
 54 //         ++t;
 55 //     }
 56 // }
 57 //v2:
 58 void BuildAC(){
 59     int h=1, t=0, i;
 60     node *nd;
 61     q[0] = rt;
 62     rt->fail = NULL;
 63     while(t < h){
 64         for(i=0; i<SZ; ++i){
 65             if(q[t]->next[i] != NULL) q[h++] = q[t]->next[i];
 66             if(q[t] == rt){
 67                 if(q[t]->next[i] == NULL) q[t]->next[i] = rt;
 68                 else q[t]->next[i]->fail = rt;
 69             }
 70             else {
 71                 nd = q[t]->fail;
 72                 if(q[t]->next[i] == NULL) q[t]->next[i] = nd->next[i];
 73                 else {
 74                     q[t]->next[i]->fail = nd->next[i];
 75                     q[t]->next[i]->unsafe |= nd->next[i]->unsafe;
 76                 }
 77             }
 78         }
 79         ++t;
 80     }
 81 }
 82 int Solve(char *s){
 83     int *bef = dp, *aft = tmp, i, j, k, n = strlen(s);
 84     node *nd;
 85     memset(bef, 0, sizeof(dp));
 86     for(i=0; i<n; ++i){
 87         memset(aft, 0x4, sizeof(dp));
 88         for(j=0; j<cur; ++j)
 89             if(ac[j].unsafe == 0){
 90                 for(k=0; k<SZ; ++k){
 91                     int idx = ac[j].next[k] - rt;
 92                     // nd = &ac[j];
 93                     // while(nd != rt && nd->next[k]==NULL) nd = nd->fail;
 94                     // if(nd->next[k] != NULL) idx = nd->next[k] - rt;
 95                     if(ac[idx].unsafe == 0){
 96                         aft[idx] = min(aft[idx], bef[j]+(c2n[s[i]]!=k));
 97                     }
 98                 }
 99                 //第一次动归从根出发
100                 if(i == 0) break;
101             }
102         swap(aft, bef);
103     }
104     n = MAX;
105     for(i=0; i<cur; ++i)
106         if(ac[i].unsafe == 0)
107             n = min(n, bef[i]);
108     return n == MAX ? -1 : n;
109 }
110
111 int main() {
112     int i, n, t=0;
113     char s[MAX];
114     rt = ac;
115     c2n[‘A‘] = 0; c2n[‘C‘] = 1; c2n[‘G‘] = 2; c2n[‘T‘] = 3;
116     while(scanf("%d", &n), n){
117         cur = 1;
118         ac[0].init();
119         for(i=0; i<n; ++i){
120             scanf("%s", s);
121             Insert(s);
122         }
123         scanf("%s",s);
124         BuildAC();
125         printf("Case %d: %d\n", ++t, Solve(s));
126     }
127 }

有兴趣的话可以参考:

http://blog.sina.com.cn/s/blog_6635898a0102e1ig.html

时间: 2024-08-24 23:10:02

poj 3769DNArepair的相关文章

POJ - 3186 Treats for the Cows (区间DP)

题目链接:http://poj.org/problem?id=3186 题意:给定一组序列,取n次,每次可以取序列最前面的数或最后面的数,第n次出来就乘n,然后求和的最大值. 题解:用dp[i][j]表示i~j区间和的最大值,然后根据这个状态可以从删前和删后转移过来,推出状态转移方程: dp[i][j]=max(dp[i+1][j]+value[i]*k,dp[i][j-1]+value[j]*k) 1 #include <iostream> 2 #include <algorithm&

POJ 2533 - Longest Ordered Subsequence(最长上升子序列) 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:http://poj.org/problem?id=2533 Description A numeric sequence of ai is ordered if a1 < a2 < ... < aN. Let the subsequence of the given numeric sequence (a1, a2, ..., aN) be any sequence (ai1, ai2, ..., aiK)

POJ——T2271 Guardian of Decency

http://poj.org/problem?id=2771 Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 5932   Accepted: 2463 Description Frank N. Stein is a very conservative high-school teacher. He wants to take some of his students on an excursion, but he is

POJ——T2446 Chessboard

http://poj.org/problem?id=2446 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 18560   Accepted: 5857 Description Alice and Bob often play games on chessboard. One day, Alice draws a board with size M * N. She wants Bob to use a lot of c

poj 1088 滑雪 DP(dfs的记忆化搜索)

题目地址:http://poj.org/problem?id=1088 题目大意:给你一个m*n的矩阵 如果其中一个点高于另一个点 那么就可以从高点向下滑 直到没有可以下滑的时候 就得到一条下滑路径 求最大的下滑路径 分析:因为只能从高峰滑到低峰,无后效性,所以每个点都可以找到自己的最长下滑距离(只与自己高度有关).记忆每个点的最长下滑距离,当有另一个点的下滑路径遇到这个点的时候,直接加上这个点的最长下滑距离. dp递推式是,dp[x][y] = max(dp[x][y],dp[x+1][y]+

POJ 1385 计算几何 多边形重心

链接: http://poj.org/problem?id=1385 题意: 给你一个多边形,求它的重心 题解: 模板题,但是不知道为啥我的结果输出的确是-0.00 -0.00 所以我又写了个 if (ans.x == 0) ans.x = 0 感觉好傻逼 代码: 1 #include <map> 2 #include <set> 3 #include <cmath> 4 #include <queue> 5 #include <stack> 6

POJ 1741 Tree(树的点分治,入门题)

Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 21357   Accepted: 7006 Description Give a tree with n vertices,each edge has a length(positive integer less than 1001).Define dist(u,v)=The min distance between node u and v.Give an in

poj 1655 树的重心

Balancing Act Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 13178   Accepted: 5565 Description Consider a tree T with N (1 <= N <= 20,000) nodes numbered 1...N. Deleting any node from the tree yields a forest: a collection of one or m

POJ 2479 Maximum sum

http://poj.org/problem?id=2479 题意: 给出一个整数串,求连续子串1和连续子串2,不相交并且串1加串2的和最大. 思路: 其实就是求最大连续和,题意要求就是求两段最大连续和.我们可以从左边和右边分别求最大连续和,代码中的dp_l[i]就是1~i的最大连续和,dp_r[i]则是i~n的最大连续和. 1 #include<iostream> 2 #include<string> 3 #include<cstring> 4 #include<