AC自动机+DP HDOJ 2457 DNA repair(DNA修复)
2016-07-14 10:18
393 查看
题目链接
题意:
给n串有疾病的DNA序列,现有一串DNA序列,问最少修改几个DNA,能使新的DNA序列不含有疾病的DNA序列。
思路:
构建AC自动机,设定end结点,dp[i][j]表示长度i的前缀串走到自动机的j点最少需要修改几个DNA。状态转移方程
。那么只要转移到下一个的DNA不是end结点就能转移,如果下一个DNA不和原序列不一样就+1。
题意:
给n串有疾病的DNA序列,现有一串DNA序列,问最少修改几个DNA,能使新的DNA序列不含有疾病的DNA序列。
思路:
构建AC自动机,设定end结点,dp[i][j]表示长度i的前缀串走到自动机的j点最少需要修改几个DNA。状态转移方程
。那么只要转移到下一个的DNA不是end结点就能转移,如果下一个DNA不和原序列不一样就+1。
#include <bits/stdc++.h> const int N = 50 + 5; const int M = 1000 + 5; const int INF = 0x3f3f3f3f; struct AC { static const int NODE = N * 20; static const int SIZE = 4; int ch[NODE][SIZE], fail[NODE], end[NODE]; int sz; void init(); int idx(char c); void insert(char *s); void get_fail(); }ac; char s[25]; char str[M]; int dp[M][AC::NODE]; int solve() { int len = strlen (str); memset (dp, INF, sizeof (dp)); dp[0][0] = 0; for (int i=1; i<=len; ++i) { for (int j=0; j<ac.sz; ++j) { if (dp[i-1][j] == INF) continue; for (int k=0; k<4; ++k) { if (!ac.end[ac.ch[j][k]]) { dp[i][ac.ch[j][k]] = std::min (dp[i][ac.ch[j][k]], dp[i-1][j] + (ac.idx (str[i-1]) != k)); } } } } int ret = INF; for (int i=0; i<ac.sz; ++i) { if (!ac.end[i]) { ret = std::min (ret, dp[len][i]); } } if (ret == INF) ret = -1; return ret; } int main() { int n, cas = 0; while (scanf ("%d", &n) == 1 && n) { ac.init (); for (int i=0; i<n; ++i) { scanf ("%s", s); ac.insert (s); } ac.get_fail (); scanf ("%s", str); printf ("Case %d: %d\n", ++cas, solve ()); } return 0; } void AC::init() { memset (ch[0], 0, sizeof (ch[0])); sz = 1; } int AC::idx(char c) { if (c == 'A') { return 0; } else if (c == 'G') { return 1; } else if (c == 'C') { return 2; } else { return 3; } } void AC::insert(char *s) { int u = 0; for (int c, i=0; s[i]; ++i) { c = idx (s[i]); if (!ch[u][c]) { memset (ch[sz], 0, sizeof (ch[sz])); end[sz] = 0; ch[u][c] = sz++; } u = ch[u][c]; } end[u] = 1; } void AC::get_fail() { fail[0] = 0; std::queue<int> que; for (int c=0; c<SIZE; ++c) { int u = ch[0][c]; if (u) { fail[u] = 0; //last[u] = 0; que.push (u); } } while (!que.empty ()) { int r = que.front (); que.pop (); for (int c=0; c<SIZE; ++c) { int &u = ch[r][c]; if (!u) { u = ch[fail[r]][c]; } else { int v = fail[r]; while (v && !ch[v][c]) v = fail[v]; fail[u] = ch[v][c]; end[u] |= end[fail[u]]; //last[u] = end[fail[u]] ? fail[u] : last[fail[u]]; que.push (u); } } } }
相关文章推荐
- Training2:位操作训练
- mybaits使用经验(1)
- sleep()和wait()方法的区别
- 2015 ACM/ICPC Asia Regional Shanghai Online
- 启动MongoDB时出现Failed to unlink socket file /tmp/mongodb-27017.sock errno:1 Operation not permitted
- Container With Most Water
- BlockChain 与 Ethereum 介绍
- 上拉刷新下拉加载xlistview--------activity_main
- 软件工程技术
- ssh中“Host key verification failed.“的解决方案
- LeetCode 373. Find K Pairs with Smallest Sums
- You are using pip version 8.0.3, however version 8.1.2 is available. You should consider upgrading v
- UVA 253 Cube painting
- mysql解决fail to open file的方法
- 【一天一道LeetCode】#217. Contains Duplicate
- 【一天一道LeetCode】#217. Contains Duplicate
- 安装Genymotion + Virtualbox 出现 “不能为虚拟电脑打开一个新任务 E_FAIL(0x80004005)”错误的解决办法
- 217. Contains Duplicate
- Ex2010-18 Exclude email address/recipient from Exchange 2010 dynamic distribution group
- 论文阅读(1)--Fine-grained Image Classification by Exploring Bipartite-Graph Labels