poj 3769DNArepair

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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

 

以上是关于poj 3769DNArepair的主要内容,如果未能解决你的问题,请参考以下文章

POJ3691DNA repair(AC自动机,DP)

ZOJ 3769 Diablo III(分组背包)

bzoj3769

[贪心] aw3769. 移动石子(模拟)

LG3769 TATT

BZOJ3769spoj 8549 BST again DP(记忆化搜索?)