DNA repair HDU - 2457 AC自动机+DP

题意:

给你N个模板串,并且给你一个文本串,

现在问你这个文本串最少需要改变几个字符才能使得它不包含任何模板串.

(以上字符只由A,T,G,C构成)

题解:

刚开始做这一题的时候表示很懵逼,好像没有学过这种类型的问题。

后面仔细想想,在之前的题目中,学会了求出不包含任何模板串的方案数。

这题可以转化下,求出所有不包含任何模板串的方案中与原串最少的不同数目。

根据这个DP

dp【i】【j】 表示走到长度为 i 的时候,在AC自动机 j 这个节点上最多与原串不同的个数。

然后这题就变成SB题了。

  1 #include <set>
  2 #include <map>
  3 #include <stack>
  4 #include <queue>
  5 #include <cmath>
  6 #include <ctime>
  7 #include <cstdio>
  8 #include <string>
  9 #include <vector>
 10 #include <cstring>
 11 #include <iostream>
 12 #include <algorithm>
 13 #include <unordered_map>
 14
 15 #define  pi    acos(-1.0)
 16 #define  eps   1e-9
 17 #define  fi    first
 18 #define  se    second
 19 #define  rtl   rt<<1
 20 #define  rtr   rt<<1|1
 21 #define  bug                printf("******\n")
 22 #define  mem(a, b)          memset(a,b,sizeof(a))
 23 #define  name2str(x)        #x
 24 #define  fuck(x)            cout<<#x" = "<<x<<endl
 25 #define  sfi(a)             scanf("%d", &a)
 26 #define  sffi(a, b)         scanf("%d %d", &a, &b)
 27 #define  sfffi(a, b, c)     scanf("%d %d %d", &a, &b, &c)
 28 #define  sffffi(a, b, c, d) scanf("%d %d %d %d", &a, &b, &c, &d)
 29 #define  sfL(a)             scanf("%lld", &a)
 30 #define  sffL(a, b)         scanf("%lld %lld", &a, &b)
 31 #define  sfffL(a, b, c)     scanf("%lld %lld %lld", &a, &b, &c)
 32 #define  sffffL(a, b, c, d) scanf("%lld %lld %lld %lld", &a, &b, &c, &d)
 33 #define  sfs(a)             scanf("%s", a)
 34 #define  sffs(a, b)         scanf("%s %s", a, b)
 35 #define  sfffs(a, b, c)     scanf("%s %s %s", a, b, c)
 36 #define  sffffs(a, b, c, d) scanf("%s %s %s %s", a, b,c, d)
 37 #define  FIN                freopen("../date.txt","r",stdin)
 38 #define  gcd(a, b)          __gcd(a,b)
 39 #define  lowbit(x)          x&-x
 40 #define  IO                 iOS::sync_with_stdio(false)
 41
 42
 43 using namespace std;
 44 typedef long long LL;
 45 typedef unsigned long long ULL;
 46 const ULL seed = 13331;
 47 const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;
 48 const int maxn = 1e6 + 7;
 49 const int maxm = 8e6 + 10;
 50 const int INF = 0x3f3f3f3f;
 51 const int mod = 1e9 + 7;
 52
 53
 54 char str[55][22], buf[1010];
 55 int n, dp[1010][1010];
 56
 57 int get_num(char ch) {
 58     if (ch == ‘A‘) return 0;
 59     if (ch == ‘T‘) return 1;
 60     if (ch == ‘C‘) return 2;
 61     if (ch == ‘G‘) return 3;
 62 }
 63
 64 struct Aho_Corasick {
 65     int next[1010][4], fail[1010], End[1010];
 66     int root, cnt;
 67
 68     int newnode() {
 69         for (int i = 0; i < 4; i++) next[cnt][i] = -1;
 70         End[cnt++] = 0;
 71         return cnt - 1;
 72     }
 73
 74     void init() {
 75         cnt = 0;
 76         root = newnode();
 77     }
 78
 79     void insert(char buf[]) {
 80         int len = strlen(buf);
 81         int now = root;
 82         for (int i = 0; i < len; i++) {
 83             if (next[now][get_num(buf[i])] == -1) next[now][get_num(buf[i])] = newnode();
 84             now = next[now][get_num(buf[i])];
 85         }
 86         End[now]++;
 87     }
 88
 89     void build() {
 90         queue<int> Q;
 91         fail[root] = root;
 92         for (int i = 0; i < 4; i++)
 93             if (next[root][i] == -1) next[root][i] = root;
 94             else {
 95                 fail[next[root][i]] = root;
 96                 Q.push(next[root][i]);
 97             }
 98         while (!Q.empty()) {
 99             int now = Q.front();
100             Q.pop();
101              if (End[fail[now]]) End[now] = 1;
102             for (int i = 0; i < 4; i++)
103                 if (next[now][i] == -1) next[now][i] = next[fail[now]][i];
104                 else {
105                     fail[next[now][i]] = next[fail[now]][i];
106                     Q.push(next[now][i]);
107                 }
108         }
109     }
110
111     int solve() {
112         int len = strlen(buf);
113         for (int i = 0; i <= len; ++i)
114             for (int j = 0; j < cnt; ++j)
115                 dp[i][j] = INF;
116         dp[0][0] = 0;
117         for (int i = 0; i < len; ++i) {
118             for (int j = 0; j < cnt; ++j) {
119                 if (dp[i][j] == INF || End[j]) continue;
120                 for (int k = 0; k < 4; ++k) {
121                     int idx = next[j][k];
122                     if (End[idx]) continue;
123                     dp[i + 1][idx] = min(dp[i + 1][idx], dp[i][j] + (get_num(buf[i]) != k));
124                 }
125             }
126         }
127         int ans = INF;
128         for (int i = 0; i < cnt; ++i) ans = min(ans, dp[len][i]);
129         if (ans == INF) return -1;
130         return ans;
131     }
132
133     void debug() {
134         for (int i = 0; i < cnt; i++) {
135             printf("id = %3d,fail = %3d,end = %3d,chi = [", i, fail[i], End[i]);
136             for (int j = 0; j < 26; j++) printf("%2d", next[i][j]);
137             printf("]\n");
138         }
139     }
140 } ac;
141
142
143 int main() {
144     //FIN;
145     int cas = 1;
146     while (sfi(n) && n) {
147         ac.init();
148         for (int i = 1; i <= n; ++i) {
149             sfs(str[i]);
150             ac.insert(str[i]);
151         }
152         ac.build();
153         sfs(buf);
154         printf("Case %d: %d\n", cas++, ac.solve());
155     }
156     return 0;
157 }

原文地址:https://www.cnblogs.com/qldabiaoge/p/11379281.html

时间: 2024-11-12 13:02:56

DNA repair HDU - 2457 AC自动机+DP的相关文章

DNA repair - HDU 2457(自动机+dp)

题目大意:给你N个DNA的串,也就是至包含'A','T','G','C'四种碱基的,这些给定的串都是带有遗传病的,然后给你一个不会超过1000的串,问你至少几个地方才能让这个串不包含遗传病,如果不论怎么修改都没用,输出'-1'   分析:用dp[Ni][nNode],表示长度为i时候到达第n个节点修改的最小次数,然后统计最后一层次最小次数就行了.   代码如下: ===================================================================

hdu 2457 AC自动机+dp

DNA repair Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2004    Accepted Submission(s): 1085 Problem Description Biologists finally invent techniques of repairing DNA that contains segments c

hdu 2296 aC自动机+dp(得到价值最大的字符串)

Ring Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3180    Accepted Submission(s): 1033 Problem Description For the hope of a forever love, Steven is planning to send a ring to Jane with a rom

Lost&#39;s revenge HDU - 3341 AC自动机+DP(需要学会如何优雅的压缩状态)

题意: 给你n个子串和一个母串,让你重排母串最多能得到多少个子串出现在重排后的母串中. 首先第一步肯定是获取母串中每个字母出现的次数,只有A T C G四种. 这个很容易想到一个dp状态dp[i][A][B][C][D] 表示在AC自动机 i 这个节点上,用了A个A,B个T,C个C,D个G. 然后我算了一下内存,根本开不下这么大的内存. 看了网上题解,然后用通过状压把,A,B,C,D压缩成一维. 这个状压就是通过进制实现需要实现唯一表示 bit[0] = 1; bit[1] = (num[0]

DNA Sequence(POJ2778 AC自动机dp+矩阵加速)

传送门 DNA Sequence Time Limit: 1000MS   Memory Limit: 65536K       Description It's well known that DNA Sequence is a sequence only contains A, C, T and G, and it's very useful to analyze a segment of DNA Sequence,For example, if a animal's DNA sequenc

HDU 2457 DNA repair (AC自动机 + DP)

题目链接:DNA repair 解析:给出n个致病DNA序列,给一段DNA片段,问最少修改多少个碱基才能修复这段DNA序列中的所有致病序列. AC自动机 + DP. 将n个致病DNA序列构成一个自动机. 令DP[i][j]表示长度为i走到节点j是所需改变的最少个数. 状态转移时,枚举下一步所有可能的碱基,然后判断该碱基是否达到匹配状态,若能,则安全转移,继续枚举下一个碱基:否则在不匹配的前提下,看该碱基加入之后是否跟上一状态相同,若不同,则需修复,即计数加一.若相同,直接转移即可.然后选择其中最

HDU2457 DNA repair(AC自动机+DP)

题目一串DNA最少需要修改几个基因使其不包含一些致病DNA片段. 这道题应该是AC自动机+DP的入门题了,有POJ2778基础不难写出来. dp[i][j]表示原DNA前i位(在AC自动机上转移i步)且后缀状态为AC自动机结点j的最少需要修改的基因数 转移我为人人型,从dp[i][j]向ATCG四个方向转移到dp[i+1][j'],如果结点被标记包含致病基因就不能转移. 1 #include<cstdio> 2 #include<cstring> 3 #include<que

Hdu 3341 Lost&#39;s revenge (ac自动机+dp+hash)

题目大意: 给出很多个DNA串,每一个串的价值为1,最后给出一个长串,要你重新排列最后的串使之它所有的子串的权值和最大. 思路分析: 最先容易想到的思路就是搜!管她3721..直接一个字符一个字符的码,然后在AC自动机上判断最后的权值.TLE哟. 然后发现搜过不去,那就dp咯.再容易想到的就是dp[i][a][b][c][d] 表示此时遍历AC自动机的节点在i,然后构成了a个A,b个G,c个C,d个T的权值. 再一看内存,500*40*40*40*40...然后...就没有然后了 再想,因为它说

HDU 2243 考研路茫茫——单词情结(AC自动机+DP+快速幂)

题目链接 错的上头了... 这题是DNA的加强版,26^1 +26^2... - A^1-A^2... 先去学了矩阵的等比数列求和,学的是第二种方法,扩大矩阵的方法.剩下就是各种模板,各种套. #include <cstdio> #include <cstring> #include <iostream> #include <map> #include <algorithm> #include <vector> #include &l