hdu2457DNA repair(ac自动机+dp)

链接

从开始节点往下走,不能走到病毒节点,如果当前状态与原始串不一样就+1,取一个最小值.

  1 #include <iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<algorithm>
5 #include<stdlib.h>
6 #include<vector>
7 #include<cmath>
8 #include<queue>
9 #include<set>
10 #include<string>
11 using namespace std;
12 #define N 1005
13 #define LL long long
14 #define INF 0xfffffff
15 const double eps = 1e-8;
16 const double pi = acos(-1.0);
17 const double inf = ~0u>>2;
18 const int child_num = 4;
19 char vir[25];
20 char s[N];
21 class AC
22 {
23 private:
24 int ch[N][child_num];
25 int fail[N];
26 int Q[N];
27 int val[N];
28 int sz;
29 int id[128];
30 char po[5];
31 int dp[N][N];
32 public:
33 void init()
34 {
35 fail[0] = 0;
36 id[‘A‘] = 0,id[‘G‘] = 1,id[‘T‘] = 2,id[‘C‘] = 3;
37 po[0] = ‘A‘,po[1] = ‘G‘,po[2] = ‘T‘,po[3] = ‘C‘;
38 }
39 void reset()
40 {
41 memset(ch[0],0,sizeof(ch[0]));
42 memset(val,0,sizeof(val));
43 sz = 1;
44 }
45 void insert(char *a,int key)
46 {
47 int p = 0;
48 for(; *a ; a++)
49 {
50 int d= id[*a];
51 if(ch[p][d]==0)
52 {
53 memset(ch[sz],0,sizeof(ch[sz]));
54 s[sz] = *a;
55 ch[p][d] = sz++;
56 }
57 p = ch[p][d];
58 }
59 val[p] = (1<<key);
60 }
61 void construct()
62 {
63 int i,head=0,tail = 0;
64 for(i = 0; i < child_num ;i++)
65 {
66 if(ch[0][i])
67 {
68 fail[ch[0][i]] = 0;
69 Q[tail++] = ch[0][i];
70 }
71 }
72 while(head!=tail)
73 {
74 int u = Q[head++];
75 val[u]|=val[fail[u]];
76 for(i = 0; i < child_num ; i++)
77 {
78 if(ch[u][i])
79 {
80 fail[ch[u][i]] = ch[fail[u]][i];
81 Q[tail++] = ch[u][i];
82 }
83 else ch[u][i] = ch[fail[u]][i];
84 }
85 }
86 }
87 void work(int n,int kk)
88 {
89 int i,j,g;
90 for(i = 0 ; i <= n ;i++)
91 for(j = 0 ;j <= sz ; j++)
92 dp[i][j] = INF;
93 dp[0][0] = 0;
94 for(i = 0 ; i < n ;i++)
95 {
96 for(j = 0 ;j < sz; j++)
97 {
98 for(g = 0 ;g < child_num ; g++)
99 {
100 if(val[ch[j][g]]) continue;
101 int o = 0;
102 if(po[g]!=s[i]) o = 1;
103 dp[i+1][ch[j][g]] = min(dp[i+1][ch[j][g]],dp[i][j]+o);
104 }
105 }
106 }
107 int ans = INF;
108 for(i = 0 ;i < sz ; i++)
109 ans = min(ans,dp[n][i]);
110 printf("Case %d: ",kk);
111 if(ans==INF)
112 puts("-1");
113 else
114 printf("%d\n",ans);
115 }
116 }ac;
117 int main()
118 {
119 int i,m,kk=0;
120 ac.init();
121 while(scanf("%d",&m)&&m)
122 {
123 ac.reset();
124 for(i = 1;i <= m ;i++)
125 {
126 scanf("%s",vir);
127 ac.insert(vir,1);
128 }
129 ac.construct();
130 scanf("%s",s);
131 int k = strlen(s);
132 ac.work(k,++kk);
133 }
134 return 0;
135 }

时间: 2024-09-30 11:01:55

hdu2457DNA repair(ac自动机+dp)的相关文章

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

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个节点,变成了

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

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,还是差点超时,代码也

poj 1625 Censored!(AC自动机+DP+高精度)

题目链接:poj 1625 Censored! 题目大意:给定N,M,K,然后给定一个N字符的字符集和,现在要用这些字符组成一个长度为M的字符串,要求不包 括K个子字符串. 解题思路:AC自动机+DP+高精度.这题恶心的要死,给定的不能匹配字符串里面有负数的字符情况,也算是涨姿势 了,对应每个字符固定偏移128单位. #include <cstdio> #include <cstring> #include <queue> #include <vector>

HDU 2296 Ring AC自动机 + DP

题意:给你n个模式串,每个模式串有一个得分,让你构造出一个长度为N之内且分数最高的文本串;输出字典序列最小的. 解题思路:  AC自动机 + DP , 不过要输出字典序列最小,多开一个 一个三维字符串来辅助二维DP(新思路) , DP[i][j] ,表示到i位置状态为j的最大得分. 解题代码: 1 // File Name: temp.cpp 2 // Author: darkdream 3 // Created Time: 2014年09月11日 星期四 15时18分4秒 4 5 #inclu