题目链接

题意:

  给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);
}
}
}
}

  

AC自动机+DP HDOJ 2457 DNA repair(DNA修复)的更多相关文章

  1. HDU 2457 DNA repair(AC自动机+DP)题解

    题意:给你几个模式串,问你主串最少改几个字符能够使主串不包含模式串 思路:从昨天中午开始研究,研究到现在终于看懂了.既然是多模匹配,我们是要用到AC自动机的.我们把主串放到AC自动机上跑,并保证不出现 ...

  2. HDU 2425 DNA repair (AC自动机+DP)

    DNA repair Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  3. HDU2457 DNA repair(AC自动机+DP)

    题目一串DNA最少需要修改几个基因使其不包含一些致病DNA片段. 这道题应该是AC自动机+DP的入门题了,有POJ2778基础不难写出来. dp[i][j]表示原DNA前i位(在AC自动机上转移i步) ...

  4. hdu 2457(ac自动机+dp)

    题意:容易理解... 分析:这是一道比较简单的ac自动机+dp的题了,直接上代码. 代码实现: #include<stdio.h> #include<string.h> #in ...

  5. 对AC自动机+DP题的一些汇总与一丝总结 (2)

    POJ 2778 DNA Sequence (1)题意 : 给出m个病毒串,问你由ATGC构成的长度为 n 且不包含这些病毒串的个数有多少个 关键字眼:不包含,个数,长度 DP[i][j] : 表示长 ...

  6. POJ1625 Censored!(AC自动机+DP)

    题目问长度m不包含一些不文明单词的字符串有多少个. 依然是水水的AC自动机+DP..做完后发现居然和POJ2778是一道题,回过头来看都水水的... dp[i][j]表示长度i(在自动机转移i步)且后 ...

  7. HDU2296 Ring(AC自动机+DP)

    题目是给几个带有价值的单词.而一个字符串的价值是 各单词在它里面出现次数*单词价值 的和,问长度不超过n的最大价值的字符串是什么? 依然是入门的AC自动机+DP题..不一样的是这题要输出具体方案,加个 ...

  8. hdu 4117 GRE Words AC自动机DP

    题目:给出n个串,问最多能够选出多少个串,使得前面串是后面串的子串(按照输入顺序) 分析: 其实这题是这题SPOJ 7758. Growing Strings AC自动机DP的进阶版本,主题思想差不多 ...

  9. HDU2296——Ring(AC自动机+DP)

    题意:输入N代表字符串长度,输入M代表喜欢的词语的个数,接下来是M个词语,然后是M个词语每个的价值.求字符串的最大价值.每个单词的价值就是单价*出现次数.单词可以重叠.如果不止一个答案,选择字典序最小 ...

随机推荐

  1. Qt &QSS

    Today task:解决了qt中的一些控件无法使用qss的问题(如QProgressDialog 调节chunk的颜色,QMessageBox按钮的颜色问题)1,对于QMessageBox,可以单独 ...

  2. C语言(Linux)中常用到的函数

    在接触Linux C之前,我比较少用到的函数,都会记录在这里.(持续更新中……) 在学习malloc()函数原理性实现时, size_t:是一种数据类型,标准C库中定义的一种类型,近似于unsigne ...

  3. Dotnet文件格式解析

    0x0.序 解析过程并没有介绍对pe结构的相关解析过程,网上此类相关资料很多可自行查阅,本文只介绍了网上资料较少的从pe结构的可选头中的数据目录表中获取dotnet目录的rva和size,到完全解析d ...

  4. BZOJ 3639: Query on a tree VII

    Description 一棵树,支持三种操作,修改点权,修改颜色,问所有与他路径上颜色相同的点的最大权,包含这两个点. Sol LCT. 用LCT来维护重边,对于每个节点在建一个set用来维护轻边,这 ...

  5. Code::Blocks如何支持C++11特性

    为了给同事分享C++11标准,需要一个演示C++11的编程环境.VS2013太大,安装起来不太方便.由于电脑上之前有安装codeblock,于是升级MinGW.去MinGW官网http://www.m ...

  6. linux无法挂载u盘

    一般插入u盘都会自动挂载,但有时挂载不了,错误提示:can't find /dev/sdb in /etc/fstab:这时可能是U盘坏了,我们当然不希望是这样.也有可能是U盘使用的接口不对应导致系统 ...

  7. 使用JHChart勾勒你想要的图表

    前言 从2016年4月14日开始,本人着手开发了JHChart图表工具库.经过断断续续的开发,截止到现在,已经实现了折线图.柱状图.饼状图.环形图和表格样式的图表功能.为了方便使用,我已经将一个简单的 ...

  8. Linux 系统中堆栈的使用方法

    本节内容概要描述了Linux内核从开机引导到系统正常运行过程中对堆栈的使用方式.这部分内容的说明与内核代码关系比较密切,可以先跳过.在开始阅读相应代码时再回来仔细研究. Linux 0.12系统中共使 ...

  9. 修复win10升级时断电inaccessible boot device

    代码提示0xc0000001 这里的解决方法对系统以及个人的没有文件丢失的影响,没有重装以及重置上丢失东西的顾虑 解决方法: WINDOWS/system32/config/RegBack/SYSTE ...

  10. Ubuntu架设FTP

    1.安装vsftpd >sudo apt-get install vsftpd 2.安装好ftp后默认是会自动创建ftp用户的,然后我们设置ftp用户的密码 >sudo passwd ft ...