HDU 2457 DNA repair(AC自动机+DP)题解
题意:给你几个模式串,问你主串最少改几个字符能够使主串不包含模式串
思路:从昨天中午开始研究,研究到现在终于看懂了。既然是多模匹配,我们是要用到AC自动机的。我们把主串放到AC自动机上跑,并保证不出现模式串,这里对AC自动机的创建有所改动,我们需要修改不存在但是符合要求的节点,如果某节点的某一子节点不存在,我们就把这个子节点指向他父辈节点存在的该节点(比如k->next[1]不存在,k->fail->next[1]存在,我们就把他改为k->next[1] = k->fail->next[1]),因为只是在AC自动机上跑,我们只关心会不会匹配到模式串。这里要当心,如果一个节点的失配指向的是模式串尾,那么这个节点也就是模式串尾。我们用dp[i][j]去储存当前匹配到主串第i位,跑到AC自动机第j个状态的最小修改,状态转移方程dp[i + 1][j-next] = min(dp[i][j->next],dp[i][j]+str[i]!=k),每次我们都从上一个状态j开始搜索满足要求的下一个状态j->next。
参考:
[Pku 3691 1625] 字符串(四) {自动机应用}
代码:
#include<cstdio>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#define ll long long
const int maxn = 1000+5;
const int maxm = 100000+5;
const int MOD = 1e7;
const int INF = 0x3f3f3f3f;
const int kind = 4;
const char baset = 0;
using namespace std;
struct Trie{
Trie *next[kind];
Trie *fail;
int flag;
int id;
};
Trie *root,point[maxn];
queue<Trie*> Q;
int head,tail,idx;
int ID(char ch){
if(ch == 'A') return 0;
else if(ch == 'C') return 1;
else if(ch == 'T') return 2;
return 3;
}
Trie* NewNode(){
Trie *temp = &point[idx];
memset(temp ->next,NULL,sizeof(temp ->next));
temp ->flag = 0;
temp ->id = idx++;
temp ->fail = NULL;
return temp;
}
void Insert(char *s){
Trie *p = root;
for(int i = 0;s[i];i++){
int x = ID(s[i]);
if(p ->next[x] == NULL){
p ->next[x] = NewNode();
}
p = p ->next[x];
}
p ->flag = 1;
}
void del(Trie *p){
if(p == NULL) return;
for(int i = 0;i < kind;i++){
if(p ->next[i])
del(p ->next[i]);
}
delete p;
}
void buildFail(){
while(!Q.empty()) Q.pop();
Q.push(root);
Trie *p,*temp;
while(!Q.empty()){
temp = Q.front();
Q.pop();
for(int i = 0;i < kind;i++){
if(temp ->next[i]){
if(temp == root){
temp ->next[i] ->fail = root;
}
else{
p = temp ->fail;
while(p){
if(p ->next[i]){
temp ->next[i] ->fail = p ->next[i];
break;
}
p = p ->fail;
}
if(p == NULL) temp ->next[i] ->fail = root;
}
if(temp ->next[i] ->fail ->flag)
temp ->next[i] ->flag = 1;
//这里要注意,如果一个节点的失配指向的是模式串尾
//那么这个节点也就是模式串尾
Q.push(temp ->next[i]);
}
else if(temp == root)
temp ->next[i] = root;
//root指向root,因为不存在这个子节点,没有限制
else
temp ->next[i] = temp ->fail ->next[i];
//指向长辈节点存在的这个子节点
}
}
}
int dp[maxn][maxn << 1]; //主串匹配到第i个,在AC自动机上走到第j个节点
int solve(char *ch){
int len = strlen(ch);
for(int i = 0;i <= len;i++)
for(int j = 0;j <= idx;j++)
dp[i][j] = INF;
dp[0][0] = 0;
for(int i = 1;i <= len;i++){
for(int j = 0;j < idx;j++){ //从这个状态j开始走,dp下一个状态
if(point[j].flag) continue; //这个状态包含模式串
if(dp[i - 1][j] == INF) continue;
for(int k = 0;k < 4;k++){
int r = point[j].next[k] ->id; //下一个点
if(point[r].flag) continue; //下一个点包含模式串
dp[i][r] = min(dp[i][r],dp[i - 1][j] + (ID(ch[i - 1]) != k));
}
}
}
int ans = INF;
for(int i = 0;i < idx;i++){
ans = min(ans,dp[len][i]);
}
if(ans == INF) return -1;
else return ans;
}
char ch[1005];
int main(){
int n,m,x,Case = 1;
while(scanf("%d",&n) != EOF && n){
idx = 0;
root = NewNode();
for(int i = 0;i < n;i++){
scanf("%s",ch);
Insert(ch);
}
buildFail();
scanf("%s",ch);
printf("Case %d: %d\n",Case++,solve(ch));
}
return 0;
}
HDU 2457 DNA repair(AC自动机+DP)题解的更多相关文章
- HDU 2457 DNA repair (AC自动机+DP)
题意:给N个串,一个大串,要求在最小的改变代价下,得到一个不含上述n个串的大串. 思路:dp,f[i][j]代表大串中第i位,AC自动机上第j位的最小代价. #include<algorithm ...
- POJ 3691 & HDU 2457 DNA repair (AC自己主动机,DP)
http://poj.org/problem?id=3691 http://acm.hdu.edu.cn/showproblem.php?pid=2457 DNA repair Time Limit: ...
- HDU 2457/POJ 3691 DNA repair AC自动机+DP
DNA repair Problem Description Biologists finally invent techniques of repairing DNA that contains ...
- HDU2457 DNA repair —— AC自动机 + DP
题目链接:https://vjudge.net/problem/HDU-2457 DNA repair Time Limit: 5000/2000 MS (Java/Others) Memory ...
- [hdu2457]DNA repair(AC自动机+dp)
题意:给出一些不合法的模式DNA串,给出一个原串,问最少需要修改多少个字符,使得原串中不包含非法串. 解题关键:多模式串匹配->AC自动机,求最优值->dp,注意在AC自动机上dp的套路. ...
- 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)
题目大意: 改动文本串的上的字符,使之不出现上面出现的串.问最少改动多少个. 思路分析: dp[i][j]表示如今 i 个字符改变成了字典树上的 j 节点. 然后顺着自己主动机一直转移方程. 注意合法 ...
- hdu 4117 GRE Words AC自动机DP
题目:给出n个串,问最多能够选出多少个串,使得前面串是后面串的子串(按照输入顺序) 分析: 其实这题是这题SPOJ 7758. Growing Strings AC自动机DP的进阶版本,主题思想差不多 ...
随机推荐
- 从CES看2016物联网发展趋势
[导读] 美国时间1月6号,千呼万唤始出来的2016年国际消费电子展(CES2016)在拉斯维加斯正式拉开序幕.三天会展完满落幕,这个被誉为全球消费电子技术风向标的北美最大消费电子展俨然变成了未来智慧 ...
- mysql 安装流程 兼容8.0.0以上版本 解决修改密码规则问题
背景介绍: 第一次安装mysql服务端,版本8.0.6 遇到了问题:1:不知道流程:2:8.0以上版本密码加密规则修改的解决方案: 1:下载mysql 服务端 https://dev.mysql. ...
- 解决Chrome关联Html文件图标显示为空白
用记事本保存为ChromeHTML.reg Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\CLSID\{42042206-2D85-1 ...
- go练习3 --map的操作
func T2_1() { // 键值string , 值 int 类型 m1 := map[string]int{} //添加一个元素 m1["str1&q ...
- Unity3D笔记五 快捷键
一.近距离查看游戏对象 在Hierarchy视图中选择游戏对象,然后在Scene视图中按快捷键“F”来近距离查看该游戏对象. 二.游戏对象不在主摄像头中? Hierarchy中双击选择需要显示的游戏对 ...
- dubbo有什么作用
转自:http://blog.csdn.net/ichsonx/article/details/39008519 1. Dubbo是什么? Dubbo是一个分布式服务框架,致力于提供高性能和透明化的R ...
- mysql格式化日期的函数
转自:https://www.cnblogs.com/duhuo/p/5650876.html mysql格式化日期 mysql查询记录如果有时间戳字段时,查看结果不方便,不能即时看到时间戳代表的 ...
- onethink----网站配置信息调用!
{:C('WEB_SITE_TITLE')} // 标题 {:C('WEB_SITE_DESCRIPTION')} // 描述 {:C('WEB_SITE_KEYWORD')} // 关键词 {:C( ...
- RGBA HSB opengl光照模型
RGBA HSB HSV颜色模型对应于画家的配色的方法.画家用改变色浓和色深的方法来从某种纯色获得不同色调的颜色.其做法是:在一种纯色中加入白色以改变色浓,加入黑色以改变色深,同时加入不同比例的白 ...
- Tickets---hdu1260 (简单dp)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1260 题意就是有n个人排队买票,每个人需要的时间是a[i] (1=< i <=N),但是现 ...