DNA repair
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 4815   Accepted: 2237

Description

Biologists finally invent techniques of repairing DNA that contains segments causing kinds of inherited diseases. For the sake of simplicity, a DNA is represented as a string containing characters 'A', 'G' , 'C' and 'T'. The repairing techniques are simply to change some characters to eliminate all segments causing diseases. For example, we can repair a DNA "AAGCAG" to "AGGCAC" to eliminate the initial causing disease segments "AAG", "AGC" and "CAG" by changing two characters. Note that the repaired DNA can still contain only characters 'A', 'G', 'C' and 'T'.

You are to help the biologists to repair a DNA by changing least number of characters.

Input

The input consists of multiple test cases. Each test case starts with a line containing one integers N (1 ≤ N ≤ 50), which is the number of DNA segments causing inherited diseases.
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.

Output

For each test case, print a line containing the test case number( beginning with 1) followed by the
number of characters which need to be changed. If it's impossible to repair the given DNA, print -1.

Sample Input

2
AAA
AAG
AAAG
2
A
TG
TGAATG
4
A
G
C
T
AGT
0

Sample Output

Case 1: 1
Case 2: 4
Case 3: -1

Source

 
 

所谓的AC自动机上的DP,就是说在AC自动机上转移,那么如果目标串不包含任何一个病毒串,那么它在Trie图上就不可能匹配成功,既然如此,那么以Trie图上某个结点为状态的DP就可以实施了......

具体先说建AC自动机,就有一个特殊的地方:

  ①:为什么要设立虚节点? 其实这个是为了底下状态转移用的,如果这个节点底下是空的,那么我们再转移时就是回到跟,因为相当于匹配完了某一个病毒串了,我们应该再匹配所有的有可能的病毒串了,如果这里不建立虚的节点,那么就需要一些特殊判定.... 会很麻烦。

②: 小主意一点就是如果某个点的fail指针指向点是危险节点,那么这个点也必然是危险节点(这是显然的)。

然后就是DP方程:  f(i,j)表示主串匹配到第i位时在自动机上的状态为j时的最少修改次数,方程大家先看着:

f(i,j.son(就是字典树的next数组))=min(f(i,j.son),f(i-1,j)+(j.son!=hash(str[i-1]))) 字符串第一位是存在0那里。(若j.son是病毒串,那么不能转移)

先看最主要的一个问题: 状态这个j.son怎么理解:  比如说当前Trie图上主串走到了abb然后开始往abbb上转移,即j.son==b,然后发现主串中第四个位置是c之类的,反正不等于b,那么想要转移过来怎么办,那么很简单,+1也就是直接修改成b即可,即有abbc变成了abbb....

  这就是AC自动机上的DP的个人认为的关键地方,那么虚拟节点的解释就很好理解了,就是它应该回到根节点去跟其他的病毒串去匹配啦.... 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm> using namespace std; const int N=;
const int INF=0x3f3f3f3f; struct Trie{
int ok;
Trie *fail;
Trie *next[];
void init(){
ok=;
fail=NULL;
memset(next,NULL,sizeof(next));
}
}*root,*q[N],a[N]; char wrd[];
char str[N];
int n,cnt,dp[N][N]; int find(char ch){
switch(ch){
case 'A':return ;
case 'C':return ;
case 'T':return ;
case 'G':return ;
}
return ;
} void InsertTrie(char *str){
Trie *loc=root;
for(int i=;str[i]!='\0';i++){
int id=find(str[i]);
if(loc->next[id]==NULL){
a[cnt].init();
loc->next[id]=&a[cnt++];
}
loc=loc->next[id];
}
loc->ok=;
} void AC_automation(){
int head=,tail=;
root->fail=NULL;
q[tail++]=root;
Trie *cur,*tmp;
while(head<tail){
cur=q[head++];
tmp=NULL;
for(int i=;i<;i++){
if(cur->next[i]==NULL){
if(cur==root) //方便DP
cur->next[i]=root;
else
cur->next[i]=cur->fail->next[i];
}else{
tmp=cur->fail;
while(tmp!=NULL){
if(tmp->next[i]!=NULL){
cur->next[i]->fail=tmp->next[i];
cur->next[i]->ok |= tmp->next[i]->ok;
break; //注意退出循环
}
tmp=tmp->fail;
}
if(tmp==NULL)
cur->next[i]->fail=root;
q[tail++]=cur->next[i];
}
}
}
} int main(){ //freopen("input.txt","r",stdin); int cases=;
while(~scanf("%d",&n) && n){
cnt=;
root=&a[cnt++];
root->init();
for(int i=;i<n;i++){
scanf("%s",wrd);
InsertTrie(wrd);
}
AC_automation();
scanf("%s",str);
int len=strlen(str);
for(int i=;i<N;i++)
for(int j=;j<N;j++)
dp[i][j]=INF;
dp[][]=;
for(int i=;i<=len;i++)
for(int j=;j<cnt;j++)
for(int k=;k<;k++){
Trie *tmp=a[j].next[k];
if(tmp->ok)
continue;
int dis=tmp-root;
dp[i][dis]=min(dp[i][dis],dp[i-][j]+(k!=find(str[i-])));
}
int ans=INF;
for(int i=;i<cnt;i++)
if(ans>dp[len][i])
ans=dp[len][i];
printf("Case %d: ",++cases);
if(ans==INF)
printf("-1\n");
else
printf("%d\n",ans);
}
return ;
}

POJ 3691 DNA repair (DP+AC自动机)的更多相关文章

  1. poj 3691 DNA repair(AC自己主动机+dp)

    DNA repair Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5877   Accepted: 2760 Descri ...

  2. poj3691 DNA repair[DP+AC自动机]

    $给定 n 个模式串,和一个长度为 m 的原串 s,求至少修改原串中的几个字符可以使得原串中不包含任一个模式串.模式串总长度 ≤ 1000,m ≤ 1000.$ 先建出模式串的AC自动机,然后考虑怎么 ...

  3. POJ 3691 DNA repair 基于AC自己主动机DP

    dp[i][j] 它表示的长度 i 下游前缀 j 更改节点的最小数量. 很清楚dp[0][0] = 0; dp[ i ][ j ] = min(dp[ i ][ j ],dp[i-1][k] + (j ...

  4. POJ 3691 DNA Sequence (AC自动机 + 矩阵 有bug,待修改)

    DNA Sequence Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9889   Accepted: 3712 Desc ...

  5. POJ 3691 DNA repair (DP+字符串)

    题意:给出nn(1≤n≤50,1≤n≤50) 个病毒DNA序列,长度均不超过20.现在给出一个长度不超过1000的字符串,求至少要更换多少个字符, 才能使这个字符串不包含这些DNA序列. 析:利用前缀 ...

  6. HDU 2457 DNA repair(AC自动机+DP)题解

    题意:给你几个模式串,问你主串最少改几个字符能够使主串不包含模式串 思路:从昨天中午开始研究,研究到现在终于看懂了.既然是多模匹配,我们是要用到AC自动机的.我们把主串放到AC自动机上跑,并保证不出现 ...

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

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

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

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

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

    DNA repair Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

随机推荐

  1. maven依赖信息获取

    1.mvn dependency:analyze 首先是"Used declared dependencies found",指项目中使用到,但是没有显示声明的依赖,如果有的话,需 ...

  2. [转]一键安装藏隐患,phpStudy批量入侵的分析与溯源

    一.前言 近日,腾讯安全云鼎实验室监测到大量主机被入侵并添加了一个名为“vusr_dx$”的隐藏帐号:同时,云鼎实验室还监测到此类帐号被大量创建的同时存在对应帐号异地登录的情况. Windows 的帐 ...

  3. HDU4183 起点到终点再到起点 除起点每点仅经过一次 网络流

    题意: T个测试数据 n个圆 下面 fre x y r 表示圆的频率 坐标和半径 要求: 从频率为400(最小的) 圆 走到频率为789(最大)的圆,再走回来,除起点每个点只能经过一次 问这样的路径是 ...

  4. android中一些特殊字符(如:←↑→↓等箭头符号)的Unicode码值

    在项目中,有时候在一些控件(如Button.TextView)中要添加一些符号,如下图所示:                          这个时候可以使用图片的方式来显示,不过这些可以直接使用U ...

  5. IE6与CSS样式兼容问题汇总

    1.PNG半透明图片的问题 虽然可以通过JS等方式解决,但依然存在载入速度等问题,所以,这个上能不要用还是尽量不要用.以达到网站最大优化. 2.IE6下的圆角 IE6不支持CSS3的圆角属性,比较好的 ...

  6. vue-router登录校验后跳转到之前指定页面如何实现

    两个需求:1.用户点击购买需要下单,并跳转到订单页面,但是如果用户没有登录的话,中间有登录验证,会拦截:2.点击购买的时候,登录校验成功了,跳转到订单页面时,订单已创建,去付款即可.3.处理拦截至登录 ...

  7. 体绘制(Volume Rendering)概述之3:光线投射算法(Ray Casting)原理和注意要点(强烈推荐呀,讲的很好)

    转自:http://blog.csdn.net/liu_lin_xm/article/details/4850609 摘抄“GPU Programming And Cg Language Primer ...

  8. Python开发接水果小游戏

    我研发的Python游戏引擎Pylash已经更新到1.4了.如今我们就来使用它完毕一个极其简单的小游戏:接水果. 下面是游戏截图: 游戏操作说明:点击屏幕左右两边或者使用键盘方向键控制人物移动.使人物 ...

  9. ArcGIS Pro体验02——启动、创建工程

    所有的猜测都是眼睛看到的,自己想到的,可能不一定正确哈. 任务界面十分简洁,左上是创建新工程,右上是账户名称,左上是关于. 可以直接创建一个工程,Blank应该是无类型,最后保存再选择:Global ...

  10. (转)解决 bitmap size exceeds VM budget (Out Of Memory 内存溢出)的问题

    在做图片处理的时候最常遇到的问题估计就是Out Of Memory (内存溢出)了 网上对这种问题的解决方案很多,原来无非就是压缩图片大小 本不该重复造轮子,但实际中却遇见了问题,写出来希望后来者能引 ...