题意:给出一些不合法的模式DNA串,给出一个原串,问最少需要修改多少个字符,使得原串中不包含非法串。

解题关键:多模式串匹配->AC自动机,求最优值->dp,注意在AC自动机上dp的套路。

AC自动机上的每个节点其实就是一种状态,进行模式匹配其实就是进行边的匹配

令$dp[i][j]$表示字符串长度为$i$时到达AC自动机上某个状态所需要修改的最小值。

转移方程:$dp[i + 1][Next[j][k]] = \min (dp[i][j] + (k! = str[i]),dp[i + 1][Next[j][k]])$

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<queue>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N=;
const int MAXN=;
ll m,n;
int dp[][MAXN];
struct Trie{
int Next[MAXN][N],Fail[MAXN],root,tot;
bool End[MAXN];
int newnode(){
for(int i=;i<N;i++) Next[tot][i]=-;
End[tot++]=false;
return tot-;
}
void init(){
tot=;
root=newnode();
}
void insert(char buf[]){
int len=strlen(buf),now=root,k;
for(int i=;i<len;i++){
if(buf[i]=='A') k=;
else if(buf[i]=='G') k=;
else if(buf[i]=='C') k=;
else k=;
if(Next[now][k]==-) Next[now][k]=newnode();
now=Next[now][k];
}
End[now]=true;
}
void build(){
queue<int>que;
Fail[root]=root;
for(int i=;i<N;i++){
if(Next[root][i]==-) Next[root][i]=root;
else{
Fail[Next[root][i]]=root;
que.push(Next[root][i]);
}
}
while(!que.empty()){
int now=que.front();
que.pop();
if(End[Fail[now]]) End[now]=true;
for(int i=;i<N;i++){
if(Next[now][i]==-) Next[now][i]=Next[Fail[now]][i];//Next指针都已经建立好
else{
Fail[Next[now][i]]=Next[Fail[now]][i];
que.push(Next[now][i]);
}
}
}
}
int solve(char buf[]){
int len=strlen(buf);
for(int i=;i<=len;i++) for(int j=;j<=tot;j++) dp[i][j]=inf;
dp[][]=;
for(int i=;i<len;i++){//最主要的事情就是分清边和点
int tmp;
if(buf[i]=='A') tmp=;
else if(buf[i]=='G') tmp=;
else if(buf[i]=='C') tmp=;
else tmp=;
for(int j=;j<tot;j++){
if(dp[i][j]==inf||End[j]) continue;
for(int k=;k<;k++){
int u=Next[j][k];
if(End[u]) continue;
dp[i+][u]=min(dp[i][j]+(tmp!=k),dp[i+][u]);
}
}
}
int ans=inf;
for(int i=;i<tot;i++) ans=min(ans,dp[len][i]);
return ans==inf?-:ans;
}
}; Trie ac;
char buf[];
int main(){
int ca=;
while(scanf("%d",&n)&&n){
ca++;
ac.init();
for(int i=;i<n;i++) scanf("%s",buf),ac.insert(buf);
ac.build();
scanf("%s",buf);
int ans=ac.solve(buf);
printf("Case %d: %d\n",ca,ans);
}
}

[hdu2457]DNA repair(AC自动机+dp)的更多相关文章

  1. HDU2457 DNA repair —— AC自动机 + DP

    题目链接:https://vjudge.net/problem/HDU-2457 DNA repair Time Limit: 5000/2000 MS (Java/Others)    Memory ...

  2. HDU 2457/POJ 3691 DNA repair AC自动机+DP

    DNA repair Problem Description   Biologists finally invent techniques of repairing DNA that contains ...

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

    题目链接 能AC还是很开心的...此题没有POJ2778那么难,那个题还需要矩阵乘法,两个题有点相似的. 做题之前,把2778代码重新看了一下,回忆一下当时做题的思路,回忆AC自动机是干嘛的... 状 ...

  4. POJ3691 DNA repair(AC自动机 DP)

    给定N个长度不超过20的模式串,再给定一个长度为M的目标串S,求在目标串S上最少改变多少字符,可以使得它不包含任何的模式串 建立Trie图,求得每个节点是否是不可被包含的串,然后进行DP dp[i][ ...

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

    题意:给N个串,一个大串,要求在最小的改变代价下,得到一个不含上述n个串的大串. 思路:dp,f[i][j]代表大串中第i位,AC自动机上第j位的最小代价. #include<algorithm ...

  6. hdu_2457_DNA repair(AC自动机+DP)

    题目连接:hdu_2457_DNA repair 题意: 给你N个字符串,最后再给你一个要匹配的串,问你最少修改多少次,使得这个串不出现之前给的N的字符串 题解: 刚学AC自动机,切这题还真不知道怎么 ...

  7. poj 2778 DNA Sequence AC自动机DP 矩阵优化

    DNA Sequence Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11860   Accepted: 4527 Des ...

  8. POJ 2778 DNA Sequence (AC自动机+DP+矩阵)

    题意:给定一些串,然后让你构造出一个长度为 m 的串,并且不包含以上串,问你有多少个. 析:很明显,如果 m 小的话 ,直接可以用DP来解决,但是 m 太大了,我们可以认为是在AC自动机图中,根据离散 ...

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

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

随机推荐

  1. sonar + ieda实现提交代码前代码校验

    代码风格不同一直是一件停头疼的事情,因为不同的工作经验,工作经历,每个人的代码风格不尽相同,造成一些代码在后期的维护当中难以维护, 查阅一些资料之后发现 idea + sonar 的方式比较适合我,实 ...

  2. SpringBoot学习之验证信息国际化

    以登录为例: 1.controller的登录方法: @RequestMapping("/SSOAuth/login") @ResponseBody public ResponseV ...

  3. C语言各种keyword

    1.register 在函数内定义变量时.默认是 auto 类型,变量存储在内存中,当程序用到该变量时,由控制器发出指令将内存中该变量的值送到运算器,计算结束后再从运算器将数据送到内存.假设一个变量用 ...

  4. 后端程序员看前端想死(二)进入页面之后js分析

    在上一篇中分析了一下以网页的组成.header中引入的乱七八糟的东西,现在进入到js中进行分析了 tuhooo啊,你是要搞前端了么? nonono,好玩,学一下 打开页面之后执行js的几种方法 直接写 ...

  5. 解压 boot.img

    ./split_bootimg.pl boot.img Page size: 2048 (0x00000800) Kernel size: 7062084 (0x006bc244) Ramdisk s ...

  6. java 重定向和转发(转载)

    jsp中result的默认类型为dispatcher. dispatcher:与<jsp:forward page=""/>效果相同 redirect:与respons ...

  7. php 去除html标记-strip_tags和htmlspecialchars的区别

    strip_tags 去掉 HTML 及 PHP 的标记. 语法: string strip_tags(string str); 传回值: 字串 函式种类: 资料处理 内容说明 本函式可去掉字串中包含 ...

  8. 九度OJ 1093:WERTYU (翻译)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:1563 解决:609 题目描述: A common typing error is to place the hands on the ke ...

  9. 在yum出问题的情况下安装某个rpm包的方法

    1 核心命令 rpm -i 2 方法 centos镜像站去找到所有的rpm包. 安装这个rpm包,发现有一个依赖没有安装,就去下载安装.因为整体的包是有限的,因此终会收敛的. 比如安装rpmbuild ...

  10. 【Windows核心编程】一个使用内存映射文件进行进程间通信的例子

    进程间通信的方式有很多种,其底层原理使用的都是内存映射文件. 本文实现了Windows核心编程第五版475页上的demo,即使用内存映射文件来在进程间通信. 进程1 按钮[Create  mappin ...