POJ 3691 DNA repair

题目大意:

给你N个致病基因(长度各不超过20), 再给你一个DNA一条链的碱基序列(长度M不超过1000), 要求尽量少的修改碱基, 使得序列不含致病基因, 不能的话输出-1.

 

简要分析:

有赤裸裸的多模式串匹配, 当然要建立AC自动机了. 把一些状态标成致病态(当然把fail指针的信心合并过来). 设f[i][s]表示到DNA的第i个碱基, 在自动机上走到s状态, 至少的修改次数. 转移就枚举AGCT进行转移就行了, 注意不能走到致病状态. 于是答案为min{f[M][s]}, s为非致病状态. 有一种类似的问题M奇大无比, 而状态数又不多, 敏感的想到矩阵乘法就行了.

 

代码实现:

View Code
  1 #include <cstdio>
2 #include <cstdlib>
3 #include <cstring>
4 #include <queue>
5 #include <algorithm>
6 using namespace std;
7
8 const int MAX_N = 50, MAX_P = 20, MAX_W = 1000, SON = 4, INF = 0x3f3f3f3f;
9 char t[MAX_P + 1], s[MAX_W + 1];
10 int n, idx[256];
11 int f[2][MAX_N * MAX_P + 1], now, pre;
12
13 struct node_t {
14 node_t *son[SON], *fail;
15 bool v;
16 } node_pool[MAX_N * MAX_P + 1], *node_idx, *root;
17
18 node_t *node_alloc() {
19 node_t *ret = node_idx ++;
20 memset(ret -> son, 0, sizeof(ret -> son));
21 ret -> fail = NULL;
22 ret -> v = 0;
23 return ret;
24 }
25
26 void init() {
27 node_idx = node_pool;
28 root = node_alloc();
29 }
30
31 void ins(char *str) {
32 node_t *pos = root;
33 while (*str) {
34 int p = idx[*(str ++)];
35 if (!pos -> son[p]) pos -> son[p] = node_alloc();
36 pos = pos -> son[p];
37 }
38 pos -> v = 1;
39 }
40
41 void build() {
42 static queue <node_t *> q;
43 for (int i = 0; i < SON; i ++)
44 if (root -> son[i]) {
45 root -> son[i] -> fail = root;
46 q.push(root -> son[i]);
47 }
48 else root -> son[i] = root;
49 while (q.size()) {
50 node_t *u = q.front();
51 q.pop();
52 for (int i = 0; i < SON; i ++)
53 if (u -> son[i]) {
54 u -> son[i] -> fail = u -> fail -> son[i];
55 u -> son[i] -> v |= u -> fail -> son[i] -> v;
56 q.push(u -> son[i]);
57 }
58 else u -> son[i] = u -> fail -> son[i];
59 }
60 }
61
62 int main() {
63 idx['A'] = 0, idx['G'] = 1, idx['C'] = 2, idx['T'] = 3;
64 int cas = 0;
65 while (scanf("%d", &n) != EOF && n) {
66 init();
67 for (int i = 0; i < n; i ++) {
68 scanf("%s", t);
69 ins(t);
70 }
71 build();
72 scanf("%s", s);
73 int sz = strlen(s);
74 int cnt = node_idx - node_pool;
75
76 now = 0, pre = 1;
77 memset(f[now], 0x3f, sizeof(f[now]));
78 f[now][0] = 0;
79 for (int i = 0; i < sz; i ++) {
80 now ^= 1, pre ^= 1;
81 memset(f[now], 0x3f, sizeof(f[now]));
82 for (int j = 0; j < cnt; j ++)
83 if (f[pre][j] < INF) {
84 node_t *pos = node_pool + j;
85 for (int k = 0; k < 4; k ++)
86 if (!pos -> son[k] -> v) {
87 int t = pos -> son[k] - node_pool;
88 f[now][t] = min(f[now][t], f[pre][j] + (k != idx[s[i]]));
89 }
90 }
91 }
92
93 printf("Case %d: ", ++ cas);
94 int ans = INF;
95 for (int i = 0; i < cnt; i ++)
96 if (!(node_pool + i) -> v) ans = min(ans, f[now][i]);
97 if (ans == INF) printf("-1\n");
98 else printf("%d\n", ans);
99 }
100 return 0;
101 }

转载于:https://www.cnblogs.com/zcwwzdjn/archive/2012/03/10/2389522.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于C++&OPENCV 的全景图像拼接 C++是一种广泛使用的编程语言,它是由Bjarne Stroustrup于1979年在新泽西州美利山贝尔实验室开始设计开发的。C++是C语言的扩展,旨在提供更强大的编程能力,包括面向对象编程和泛型编程的支持。C++支持数据封装、继承和多态等面向对象编程的特性和泛型编程的模板,以及丰富的标准库,提供了大量的数据结构和算法,极大地提高了开发效率。12 C++是一种静态类型的、编译式的、通用的、大小写敏感的编程语言,它综合了高级语言和低级语言的特点。C++的语法与C语言非常相似,但增加了许多面向对象编程的特性,如类、对象、封装、继承和多态等。这使得C++既保持了C语言的低级特性,如直接访问硬件的能力,又提供了高级语言的特性,如数据封装和代码重用。13 C++的应用领域非常广泛,包括但不限于教育、系统开发、游戏开发、嵌入式系统、工业和商业应用、科研和高性能计算等领域。在教育领域,C++因其结构化和面向对象的特性,常被选为计算机科学和工程专业的入门编程语言。在系统开发领域,C++因其高效性和灵活性,经常被作为开发语言。游戏开发领域中,C++由于其高效性和广泛应用,在开发高性能游戏和游戏引擎中扮演着重要角色。在嵌入式系统领域,C++的高效和灵活性使其成为理想选择。此外,C++还广泛应用于桌面应用、Web浏览器、操作系统、编译器、媒体应用程序、数据库引擎、医疗工程和机器人等领域。16 学习C++的关键是理解其核心概念和编程风格,而不是过于深入技术细节。C++支持多种编程风格,每种风格都能有效地保证运行时间效率和空间效率。因此,无论是初学者还是经验丰富的程序员,都可以通过C++来设计和实现新系统或维护旧系统。3

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值