poj3691 DNA repair[DP+AC自动机]
$给定 n 个模式串,和一个长度为 m 的原串 s,求至少修改原串中的几个字符可以使得原串中不包含任一个模式串。模式串总长度 ≤ 1000,m ≤ 1000。$
先建出模式串的AC自动机,然后考虑怎么求最优解。考虑AC自动机上DP,设$f_{i,j}$走了$i$步之后在$j$节点时候的最少修改次数。
标记处所有不能走到的点(即走到就匹配了的点,即后缀为某一模式串的所有点),走点的时候应当回避这些点,转移的时候向合法的状态转移,分两种。
一种沿着原串$s_i$走,$f_{i+1,to_j}\leftarrow f_{i,j}$,另一种是走其他路,$f_{i+1,to_j'}\leftarrow f_{i,j}+1$。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define dbg(x) cerr << #x << " = " << x <<endl
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
template<typename T>inline T _min(T A,T B){return A<B?A:B;}
template<typename T>inline T _max(T A,T B){return A>B?A:B;}
template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,):;}
template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,):;}
template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
template<typename T>inline T read(T&x){
x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
}
const int N=+,INF=0x3f3f3f3f;
int ha[],tr[N][],ban[N],nxt[N],legal[N],cnt,tot;
char s[N];
int n;
inline void Insert(){
int len=strlen(s+),x=;
for(register int i=,c=ha[s[]];i<=len;++i,c=ha[s[i]]){
if(!tr[x][c])tr[x][c]=++tot;
x=tr[x][c];
}
ban[x]=;
}
queue<int> q;
inline void Build(){
legal[cnt=]=;
memset(nxt,,sizeof nxt);
for(register int i=;i<;++i)if(tr[][i])nxt[tr[][i]]=,q.push(tr[][i]);
while(!q.empty()){
int x=q.front();q.pop();
if(ban[nxt[x]])ban[x]=;
if(!ban[x])legal[++cnt]=x;
for(register int i=;i<;++i)
if(tr[x][i])nxt[tr[x][i]]=tr[nxt[x]][i],q.push(tr[x][i]);
else tr[x][i]=tr[nxt[x]][i];
}
}
#define j legal[_]
int f[N][N],ans,T;
inline void dp(){
memset(f,0x3f,sizeof f);
f[][]=;ans=INF;
int len=strlen(s+);
for(register int i=;i<len;++i)
for(register int _=;_<=cnt;++_)if(f[i][j]<INF){
int c=ha[s[i+]];//dbg(i),dbg(j),dbg(f[i][j]);
for(register int k=;k<;++k)
if(!ban[tr[j][k]]&&(c^k))
MIN(f[i+][tr[j][k]],f[i][j]+);
if(!ban[tr[j][c]])MIN(f[i+][tr[j][c]],f[i][j]);
}
for(register int _=;_<=cnt;++_)MIN(ans,f[len][j]);
}
#undef j
int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
ha['A']=,ha['C']=,ha['G']=,ha['T']=;
while(read(n)){
memset(ban,,sizeof ban);memset(tr,,sizeof tr),tot=;
for(register int i=;i<=n;++i)scanf("%s",s+),Insert();
Build();scanf("%s",s+);dp();
printf("Case %d: %d\n",++T,ans<INF?ans:-);
}
return ;
}
总结:AC自动机上DP多为$f_{i,j}$型状态设计,需要考虑每一步各种转移情况。过于浅薄
poj3691 DNA repair[DP+AC自动机]的更多相关文章
- HDU 2457 DNA repair(AC自动机+DP)题解
题意:给你几个模式串,问你主串最少改几个字符能够使主串不包含模式串 思路:从昨天中午开始研究,研究到现在终于看懂了.既然是多模匹配,我们是要用到AC自动机的.我们把主串放到AC自动机上跑,并保证不出现 ...
- 【POJ3691】 DNA repair (AC自动机+DP)
DNA repair Time Limit: 2000MS Memory Limit: 65536KB 64bit IO Format: %I64d & %I64u Description B ...
- HDU 2425 DNA repair (AC自动机+DP)
DNA repair Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- HDU2457 DNA repair(AC自动机+DP)
题目一串DNA最少需要修改几个基因使其不包含一些致病DNA片段. 这道题应该是AC自动机+DP的入门题了,有POJ2778基础不难写出来. dp[i][j]表示原DNA前i位(在AC自动机上转移i步) ...
- 【POJ3691】DNA repair(AC自动机,DP)
题意: 生物课上我们学到,DNA序列中只有A, C, T和G四种片段. 经科学发现,DNA序列中,包含某些片段会产生不好的基因,如片段"ATC"是不好片段,则"AGATC ...
- 咕咕(数位dp+AC自动机)
咕咕(数位dp+AC自动机) 若一个字符串的字符集合是0~m-1,那么称它为m进制字符串.给出n个m进制字符串\(s_i\),每个字符串的权值为\(v_i\).对于另一个m进制字符串\(S\),设\( ...
- 洛谷$P4045\ [JSOI2009]$密码 $dp$+$AC$自动机
正解:$dp$+$AC$自动机+搜索 解题报告: 传送门$QwQ$ 首先显然先建个$AC$自动机,然后考虑设$f_{i,j,k}$表示长度为$i$,现在在$AC$自动机的第$j$个位置,已经表示出来的 ...
- POJ 3691 DNA repair (DP+AC自动机)
DNA repair Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 4815 Accepted: 2237 Descri ...
- 【AC自动机】【动态规划】poj3691 DNA repair
http://blog.csdn.net/kk303/article/details/6929641 http://blog.csdn.net/human_ck/article/details/657 ...
随机推荐
- golang break label 与goto label
本文链接:https://blog.csdn.net/itbsl/article/details/73380537 与其他语言一样,Go语言也支持label(标签)语法:分别是break label和 ...
- Ubuntu更换科大源
更换科大源 方案一:在命令行输入 sudo gedit /etc/apt/sources.list ,打开系统自带源文件. 将文件内源删除,更换为以下科大源: deb http://mirrors.a ...
- [转帖]SSH原理与运用(一):远程登录
http://www.ruanyifeng.com/blog/2011/12/ssh_remote_login.html 写的很好.. 自己才简单明白了一点东西.. SSH是每一台Linux电脑的标准 ...
- Spring学习笔记(一)
Spring学习笔记(一) 这是一个沉淀的过程,大概第一次接触Spring是在去年的这个时候,当初在实训,初次接触Java web,直接学习SSM框架(当是Servlet都没有学),于是,养成了一个很 ...
- Python【print函数】
下面是 print函数的一种用法,用逗号隔开,可在同一行打印不同类型的数据.x = input('请你输入被除数:')y = input('请你输入除数:')z = float(x)/float(y) ...
- 屹今为止最好用的HTTP客户端命令行工具-接口调试神器HTTPie
一.思考❓❔ 1.你用过哪些http客户端调试工具? Postman 不够灵活 需要打开客户端, 麻烦 学习成本高 Jmeter 臃肿 麻烦 学习成本高 curl 参数多, 记不住 不够灵活 主要在L ...
- Elastic Search中DSL Query的常见语法
Query DSL是一种通过request body提交搜索参数的请求方式.就是将请求头参数(?xxx=xxx)转换为请求体参数.语法格式:GET [/index_name/type_name]/_s ...
- MouseMoveEvent为了不太耗资源在默认状态下是要鼠标按下才能捕捉到。要想鼠标不按下时的移动也能捕捉到,需要setMouseTracking(true)
最近用Qt软件界面,需要用到mouseMoveEvent,研究了下,发现些问题,分享一下. 在Qt中要捕捉鼠标移动事件需要重写MouseMoveEvent,但是MouseMoveEvent为了不太耗资 ...
- 怎样理解 Vue 项目的目录结构?
Vue 项目的目录结构如下, 我们将会在后面逐个去了解它们的作用: 01. build - 存储项目构建相关的代码, 比如 webpack. 02. config - Vue 的配置目录,包括端口 ...
- JavaScript设计模式(发布订阅模式)
发布—订阅模式又叫观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知.在JavaScript开发中,我们一般用事件模型来替代传统的发布—订阅模式 ...