【POJ3691】DNA repair(AC自动机,DP)

题意:

生物课上我们学到,DNA序列中只有A, C, T和G四种片段。

经科学发现,DNA序列中,包含某些片段会产生不好的基因,如片段”ATC”是不好片段,则”AGATCC”, “CATCAA”, “ATCATC”都是不好的DNA序列,这些不好片段我们可以称为病毒片段

现在已知m个病毒片段, 然后给定一个DNA串,问如果使用最少的修改(将DNA中的某个字母,变为其他字母,比如A变T,但变的字母也只能是”ACTG”),使得这个DNA串不包含病毒片段

【数据规模和约定】

1<=m<=50  病毒片段长度不超过20,只含A,T,C,G字母

DNA串长度不超过1000, 只含A, T, C, G字母

思路:AC自动机上的DP

判断是否病毒部分与上一道相同

设dp[i,j]为在原串上前i个字母上改,现在在自动机上j号节点的最小值

\[ dp[i,x]=min\begin{cases} dp[i-1,j] (k=ch[i])\\dp[i-1,j]+1 (k<>ch[i])\end{cases} \]

其中x为j号节点走字母k之后所到达的节点号,要求j号节点为合法节点

答案即为\[ min(dp[len,i]) (i为合法节点) \]

 1 const s:array[1..4]of char=(‘A‘,‘C‘,‘G‘,‘T‘);
 2       oo=500000000;
 3 var map:array[1..1100,‘A‘..‘T‘]of longint;
 4     dp:array[0..1100,0..1000]of longint;
 5     b,f:array[0..1100]of longint;
 6     q:array[1..200000]of longint;
 7     n,tot,i,j,k,d,ans,num,p,cas:longint;
 8     ch:ansistring;
 9
10
11 procedure build;
12 var i,d,u:longint;
13 begin
14  u:=1; d:=length(ch);
15  for i:=1 to d do
16  begin
17   if map[u,ch[i]]=0 then begin inc(num); map[u,ch[i]]:=num; end;
18   u:=map[u,ch[i]];
19  end;
20  b[u]:=1;
21 end;
22
23 procedure acauto;
24 var t,w,u,p,son,i:longint;
25 begin
26  t:=0; w:=1; q[1]:=1;
27  while t<w do
28  begin
29   inc(t); u:=q[t];
30   if b[f[u]]=1 then b[u]:=1;
31   for i:=1 to 4 do
32    if map[u,s[i]]>0 then
33    begin
34     son:=map[u,s[i]];
35     p:=f[u];
36     if u=1 then f[son]:=1
37      else f[son]:=map[p,s[i]];
38     inc(w); q[w]:=son;
39    end
40     else
41     begin
42      p:=f[u];
43      if u=1 then map[u,s[i]]:=1
44       else map[u,s[i]]:=map[p,s[i]];
45     end;
46  end;
47 end;
48
49 function min(x,y:longint):longint;
50 begin
51  if x<y then exit(x);
52  exit(y);
53 end;
54
55 begin
56  assign(input,‘poj3691.in‘); reset(input);
57  assign(output,‘poj3691.out‘); rewrite(output);
58  while not eof do
59  begin
60   fillchar(f,sizeof(f),0);
61   fillchar(b,sizeof(b),0);
62   fillchar(dp,sizeof(dp),$1f);
63   for i:=1 to num do
64    for j:=1 to 4 do map[i,s[j]]:=0;
65   readln(n);
66   if n=0 then break;
67   num:=1; inc(cas);
68   for i:=1 to n do
69   begin
70    readln(ch);
71    build;
72   end;
73   acauto;
74   readln(ch);
75   dp[0,1]:=0; d:=length(ch);
76   for i:=1 to d do
77    for j:=1 to num do
78     if (b[j]=0)and(dp[i-1,j]<oo) then
79      for k:=1 to 4 do
80      begin
81       p:=map[j,s[k]];
82       if b[p]=0 then
83       begin
84        if ch[i]=s[k] then dp[i,p]:=min(dp[i,p],dp[i-1,j])
85         else dp[i,p]:=min(dp[i,p],dp[i-1,j]+1);
86       end;
87      end;
88   ans:=oo;
89   for i:=1 to num do
90    if b[i]=0 then ans:=min(ans,dp[d,i]);
91   write(‘Case ‘,cas,‘: ‘);
92   if ans<oo then writeln(ans)
93    else writeln(-1);
94  end;
95  close(input);
96  close(output);
97 end.
时间: 2024-12-27 05:27:36

【POJ3691】DNA repair(AC自动机,DP)的相关文章

POJ 3691 DNA repair AC自动机 + DP

题意:给你只包含‘A’,‘G’,‘T’,‘C’四个字母的n个模板串和1个文本串,问你文本串改变多少个字符就可以使得文本串中没有一个模板串 解题思路: 我们可以知道  dp[i][j] 为文本串到 第i 个字符  AC自动机状态为j的最少的变换次数(这里为什么要用AC自动机,因为end数组可以记录哪一个状态是结束的,而且处理以后可以知道那些后缀等于前缀--也就是不能到达,因为如果能够到达的话那么状态更新就会产生错误.),这样dp即可 解题代码: 1 // File Name: temp.cpp 2

HDU 2457 DNA repair AC自动机 + dp

http://acm.hdu.edu.cn/showproblem.php?pid=2457 首先把病毒串保存一下,然后对于每一个trie上的节点,跑一发AC自动机,建立一个trie图. 建立的时候,对应做一些修改. 比如,现在建立成了这个样子. 如果he是一个病毒串,那么应该相对应的,把she那个he的位置,标志上,它也是病毒串,也就是不能转移到这一个状态. 这个可以在buildfail的时候对应修改. dp, 设dp[i][j],表示处理到字符串的第i个,走到了AC自动机的第j个节点,变成了

POJ 3691 &amp; 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: 2000MS   Memory Limit: 65536K Total Submissions: 5690   Accepted: 2669 Description Biologists finally invent techniques of repairing DNA that contain

poj3691--DNA repair(AC自动机+dp)

DNA repair Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5743   Accepted: 2693 Description Biologists finally invent techniques of repairing DNA that contains segments causing kinds of inherited diseases. For the sake of simplicity, a

hdu2457---DNA repair(AC自动机+dp)

Problem 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 repai

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

题目链接:DNA repair 解析:给出n个致病DNA序列,给一段DNA片段,问最少修改多少个碱基才能修复这段DNA序列中的所有致病序列. AC自动机 + DP. 将n个致病DNA序列构成一个自动机. 令DP[i][j]表示长度为i走到节点j是所需改变的最少个数. 状态转移时,枚举下一步所有可能的碱基,然后判断该碱基是否达到匹配状态,若能,则安全转移,继续枚举下一个碱基:否则在不匹配的前提下,看该碱基加入之后是否跟上一状态相同,若不同,则需修复,即计数加一.若相同,直接转移即可.然后选择其中最

HDU2457 DNA repair(AC自动机+DP)

题目一串DNA最少需要修改几个基因使其不包含一些致病DNA片段. 这道题应该是AC自动机+DP的入门题了,有POJ2778基础不难写出来. dp[i][j]表示原DNA前i位(在AC自动机上转移i步)且后缀状态为AC自动机结点j的最少需要修改的基因数 转移我为人人型,从dp[i][j]向ATCG四个方向转移到dp[i+1][j'],如果结点被标记包含致病基因就不能转移. 1 #include<cstdio> 2 #include<cstring> 3 #include<que

hdu 2457 AC自动机+dp

DNA repair Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2004    Accepted Submission(s): 1085 Problem Description Biologists finally invent techniques of repairing DNA that contains segments c

HDU3341 Lost&#39;s revenge(AC自动机+DP)

题目是给一个DNA重新排列使其包含最多的数论基因. 考虑到内存大概就只能这么表示状态: dp[i][A][C][G][T],表示包含各碱基个数为ACGT且当前后缀状态为自动机第i的结点的字符串最多的数论基因数 其中ACGT可以hash成一个整数(a*C*G*T+c*G*T+g*T+T),这样用二维数组就行了,而第二维最多也就11*11*11*11个. 接下来转移依然是我为人人型,我是丢进一个队列,用队列来更新状态的值. 这题果然挺卡常数的,只好手写队列,最后4500msAC,还是差点超时,代码也

Hdu 3341 Lost&#39;s revenge (ac自动机+dp+hash)

题目大意: 给出很多个DNA串,每一个串的价值为1,最后给出一个长串,要你重新排列最后的串使之它所有的子串的权值和最大. 思路分析: 最先容易想到的思路就是搜!管她3721..直接一个字符一个字符的码,然后在AC自动机上判断最后的权值.TLE哟. 然后发现搜过不去,那就dp咯.再容易想到的就是dp[i][a][b][c][d] 表示此时遍历AC自动机的节点在i,然后构成了a个A,b个G,c个C,d个T的权值. 再一看内存,500*40*40*40*40...然后...就没有然后了 再想,因为它说