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的进阶版本,主题思想差不多 ...
随机推荐
- Compass(更新中。。。)
compass Compass是Sass的工具库,就好像jQuery是js的库一样. sass有了compass的配合,就会更加事半功倍. Sass本身只是一个编译器,Compass在它的基础上,封装 ...
- sencha touch 问题汇总
做sencha touch有一段时间了,目前而言,sencha touch在android上问题比较严重,在此对android中sencha touch的问题做一些汇总: 1.内存问题: 打包成安装程 ...
- SDOI 2016 Round1 Day2
生成魔咒 /* 后缀数组+双向链表 参照:https://blog.csdn.net/clove_unique/article/details/53911757 */ #include<cstd ...
- .net Asp AdRotator(广告控件)
1.新建项目名称AdRotator 2.右键项目名称添加一个xml文件命名为AdRotator.xml <?xml version="1.0" encoding=" ...
- 从一个多项目Web工程看Eclipse如何导入Gradle项目
这里再次说一下为什么我们需要熟悉Gradle构建工具,主要原因就是很多开源项目现在都在改用Gradle作为构建工具.一部分的github上的示例代码也在用Gradle构建,如果还是只能用maven,那 ...
- HDU Humble Numbers
Problem Description A number whose only prime factors are 2,3,5 or 7 is called a humble number. The ...
- html 标准属性不要用 setAttribute 方法
html 中有些属性,譬如 checked , autofocus 只要存在就会有效,即使值是 false ,譬如: <input autofocus=false id='test'> & ...
- 【css预处理器】------css预处理器及sass基本介绍------【巷子】
001.什么是css预处理器? css预处理器定义了一种新的语言.用一种专门的编程语言,为css增加了一些编程的特性,将css作为目标生成文件,然后开发者就只要使用这种语言进行编码工作.(通俗点说“” ...
- CH0601 Genius ACM【倍增】【归并排序】
0601 Genius ACM 0x00「基本算法」例题 描述 给定一个整数 M,对于任意一个整数集合 S,定义“校验值”如下: 从集合 S 中取出 M 对数(即 2∗M 个数,不能重复使用集合中的数 ...
- Fast and Accurate Traffic Matrix Measurement Using Adaptive Cardinality Counting
paper-CaiPan.pdf http://conferences.sigcomm.org/sigcomm/2005/paper-CaiPan.pdf