HDU2457 DNA repair —— AC自动机 + DP
题目链接:https://vjudge.net/problem/HDU-2457
DNA repair
Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3126 Accepted Submission(s): 1661
You are to help the biologists to repair a DNA by changing least number of characters.
The following N lines gives N non-empty strings of length not greater than 20 containing only characters in "AGCT", which are the DNA segments causing inherited disease.
The last line of the test case is a non-empty string of length not greater than 1000 containing only characters in "AGCT", which is the DNA to be repaired.
The last test case is followed by a line containing one zeros.
number of characters which need to be changed. If it's impossible to repair the given DNA, print -1.
AAA
AAG
AAAG
2
A
TG
TGAATG
4
A
G
C
T
AGT
0
Case 2: 4
Case 3: -1
题意:
给出n个遗传病DNA序列,以及一个人体DNA序列,问至少修改多少个脱氧核苷酸,使得人体DNA序列不含遗传病?
题解:
1.将n个序列插入AC自动机。
2.设dp[i][j]为:处理到第i个字符,且当前状态为j(自动机上的状态)的最少修改数。
3.AC自动机实际上是一张有向图,如果要求字符串不含有自动机里面的病毒,那么字符串只能沿着自动机上的边走,当然需要去除病毒结点。所以状态转移:当字符串中的第i个字符与状态j的字符相同,那么dp[i+1][newj] = dp[i][j],否则dp[i+1][newj] = dp[i][j] + 1,dp[i+1][newj]取最小值即可。
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const double EPS = 1e-;
const int INF = 2e9;
const LL LNF = 9e18;
const int MOD = 1e5;
const int MAXN = 1e3+; int Map[];
char M[];
int dp[MAXN][MAXN];
struct Trie
{
int sz, base;
int next[MAXN][], fail[MAXN], end[MAXN];
int root, L;
int newnode()
{
for(int i = ; i<sz; i++)
next[L][i] = -;
end[L++] = false;
return L-;
} void init(int _sz, int _base)
{
sz = _sz;
base = _base;
L = ;
root = newnode();
}
void insert(char buf[])
{
int len = strlen(buf);
int now = root;
for(int i = ; i<len; i++)
{
if(next[now][Map[buf[i]]] == -) next[now][Map[buf[i]]] = newnode();
now = next[now][Map[buf[i]]];
}
end[now] |= true;
}
void build()
{
queue<int>Q;
fail[root] = root;
for(int i = ; i<sz; i++)
{
if(next[root][i] == -) next[root][i] = root;
else fail[next[root][i]] = root, Q.push(next[root][i]);
}
while(!Q.empty())
{
int now = Q.front();
Q.pop();
end[now] |= end[fail[now]]; //当前串的后缀是否也包含单词
for(int i = ; i<sz; i++)
{
if(next[now][i] == -) next[now][i] = next[fail[now]][i];
else fail[next[now][i]] = next[fail[now]][i], Q.push(next[now][i]);
}
}
} int query(char s[])
{
int len = strlen(s);
for(int i = ; i<=len; i++)
for(int j = ; j<L; j++)
dp[i][j] = INF; dp[][] = ;
for(int i = ; i<len; i++)
for(int j = ; j<L; j++)
{
if(end[j] || dp[i][j]==INF) continue;
for(int k = ; k<sz; k++)
{
int newi = i+;
int newj = next[j][k];
if(end[newj]) continue;
dp[newi][newj] = min(dp[newi][newj], dp[i][j]+(s[i]!=M[k]));
}
} int ret = INF;
for(int i = ; i<L; i++)
ret = min(ret, dp[len][i]);
return ret==INF?-:ret;
}
}; Trie ac;
char buf[MAXN];
int main()
{
Map['A'] = ; Map['C'] = ; Map['G'] = ; Map['T'] = ; //离散化
M[] = 'A'; M[] = 'C'; M[] = 'G'; M[] = 'T';
int n, kase = ;
while(scanf("%d", &n) && n)
{
ac.init(,'A');
for(int i = ; i<=n; i++)
{
scanf("%s", buf);
ac.insert(buf);
}
ac.build();
scanf("%s", buf);
int ans = ac.query(buf);
printf("Case %d: %d\n", ++kase, ans);
}
return ;
}
HDU2457 DNA repair —— AC自动机 + DP的更多相关文章
- [hdu2457]DNA repair(AC自动机+dp)
题意:给出一些不合法的模式DNA串,给出一个原串,问最少需要修改多少个字符,使得原串中不包含非法串. 解题关键:多模式串匹配->AC自动机,求最优值->dp,注意在AC自动机上dp的套路. ...
- HDU 2457/POJ 3691 DNA repair AC自动机+DP
DNA repair Problem Description Biologists finally invent techniques of repairing DNA that contains ...
- POJ 3691 DNA repair(AC自动机+DP)
题目链接 能AC还是很开心的...此题没有POJ2778那么难,那个题还需要矩阵乘法,两个题有点相似的. 做题之前,把2778代码重新看了一下,回忆一下当时做题的思路,回忆AC自动机是干嘛的... 状 ...
- POJ3691 DNA repair(AC自动机 DP)
给定N个长度不超过20的模式串,再给定一个长度为M的目标串S,求在目标串S上最少改变多少字符,可以使得它不包含任何的模式串 建立Trie图,求得每个节点是否是不可被包含的串,然后进行DP dp[i][ ...
- HDU 2457 DNA repair (AC自动机+DP)
题意:给N个串,一个大串,要求在最小的改变代价下,得到一个不含上述n个串的大串. 思路:dp,f[i][j]代表大串中第i位,AC自动机上第j位的最小代价. #include<algorithm ...
- hdu_2457_DNA repair(AC自动机+DP)
题目连接:hdu_2457_DNA repair 题意: 给你N个字符串,最后再给你一个要匹配的串,问你最少修改多少次,使得这个串不出现之前给的N的字符串 题解: 刚学AC自动机,切这题还真不知道怎么 ...
- poj 2778 DNA Sequence AC自动机DP 矩阵优化
DNA Sequence Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 11860 Accepted: 4527 Des ...
- POJ 2778 DNA Sequence (AC自动机+DP+矩阵)
题意:给定一些串,然后让你构造出一个长度为 m 的串,并且不包含以上串,问你有多少个. 析:很明显,如果 m 小的话 ,直接可以用DP来解决,但是 m 太大了,我们可以认为是在AC自动机图中,根据离散 ...
- HDU2457 DNA repair(AC自动机+DP)
题目一串DNA最少需要修改几个基因使其不包含一些致病DNA片段. 这道题应该是AC自动机+DP的入门题了,有POJ2778基础不难写出来. dp[i][j]表示原DNA前i位(在AC自动机上转移i步) ...
随机推荐
- 【开发总结】—— BABYLON 项目开发必备系列
前言:在公司主要使用Babylon.js作为前端引擎,我自己在开发中总结到基本上每一个新项目都会需要这些基本设置. 一.ios兼容:解决镜面反射 如果不加offline,材质中有镜面反射,苹果手机 ...
- BZOJ 1878 SDOI2009 HH的项链 树状数组/莫队算法
题目大意:给定一个序列.求一个区间内有多少个不同的数 正解是树状数组 将全部区间依照左端点排序 然后每次仅仅统计左端点開始的每种颜色的第一个数即可了 用树状数组维护 我写的是莫队算法 莫队明显能搞 m ...
- 135 - ZOJ Monthly, August 2014
135 - ZOJ Monthly, August 2014 A:构造问题,推断序列奇偶性.非常easy发现最小值不是1就是0.最大值不是n就是n - 1,注意细节去构造就可以 E:dp.dp[i][ ...
- 微信小程序(应用号)开发新闻客户端的实战课程
摘要: 本实例将演示从零开发一个微信应用号的过程,页面轮播与跳转传值,实现单元格自定义布局,全部源码可通过github下载. 下载最新版的微信小程序开发工具,目前是v0.9.092300 下载地址:h ...
- Odoo11 重大改变
Table of Contents 新特性 Activity 项目子任务 组织架构 地址 域 widget 功能重构 Quant 份 procurement 补货 自动动作 动作绑定 去掉了stock ...
- Shell脚本值:运算符
算术运算符 原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用. expr 是一款表达式计算工具,使用它能完成表达式的求值操作. 例如:实现两个 ...
- 对于Json和对象转换的学习
学习这个的用处有非常多的: 在传输数据过程中比較查看数据比較清晰,代码也较清晰.也能够避免split函数带来的隐藏bug 当然也有不足: 准备工具较繁琐,须要准备对象(当然 ...
- oracle 使用job定时自动重置sequence
一.赋予用户创建和删除sequence的权限 grant create any sequence to user_name; grant drop any sequnce to user_name; ...
- iReport+jasperreport创建子表的几种方式(1)
在制作报表的过程中,子表是不可缺少的.今天就研究了一下制作子表的几种方式 一.连接数据库创建子表 以MySQL为例: 我的数据源数据库中的表 watermark/2/text/aHR0cDovL2Js ...
- 从英语单词shell想到的
shell当初听到以为很高级 后来才知道只是壳而已 百度百科中解释为 shell 在计算机科学中,Shell俗称壳(用来区别于核),是指“提供使用者使用界面”的软件(命令解析器).它类似于DOS下的c ...