HDU 2457 DNA_repair

DNA repair

Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2530    Accepted Submission(s): 1356
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 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
 
基础的AC自动机DP,按长度一层层前向转移
 
  1 #include <iostream>
  2 #include <cstdlib>
  3 #include <cstdio>
  4 #include <algorithm>
  5 #include <string>
  6 #include <cstring>
  7 #include <cmath>
  8 #include <map>
  9 #include <stack>
 10 #include <set>
 11 #include <vector>
 12 #include <queue>
 13 #include <time.h>
 14 #define eps 1e-7
 15 #define INF 0x3f3f3f3f
 16 #define MOD 1000000007
 17 #define rep0(j,n) for(int j=0;j<n;++j)
 18 #define rep1(j,n) for(int j=1;j<=n;++j)
 19 #define pb push_back
 20 #define set0(n) memset(n,0,sizeof(n))
 21 #define ll long long
 22 #define ull unsigned long long
 23 #define iter(i,v) for(edge *i=head[v];i;i=i->next)
 24 //#define max(a,b) (a>b?a:b)
 25 //#define min(a,b) (a<b?a:b)
 26 //#define OJ
 27 using namespace std;
 28 const int MAXINT = 1110;
 29 const int MAXNODE = 1110;
 30 const int MAXEDGE = 1110;
 31 int n, T;
 32 char s[MAXINT];
 33 struct node {
 34     node *fail;
 35     node *c[4];
 36     int bad;
 37     int nd[MAXINT]; //for a string of length i, least change required to reach this state
 38 };
 39 int toint(char c) {
 40     switch (c) {
 41     case 'A': return 0;
 42     case 'C': return 1;
 43     case 'G': return 2;
 44     case 'T': return 3;
 45     }
 46     return 0;
 47 }
 48 struct ac_automaton {
 49     node mp[MAXNODE];
 50     node *root, *pre;
 51     node *q[MAXNODE];
 52     int cnt;
 53     ac_automaton() {
 54         memset(mp, 0, sizeof(mp));
 55         memset(q, 0, sizeof(q));
 56         cnt = 0;
 57         root = new_node();
 58         pre = root;
 59     }
 60     void clear() {
 61         memset(mp, 0, sizeof(mp));
 62         memset(q, 0, sizeof(q));
 63         cnt = 0;
 64         root = new_node();
 65         pre = root;
 66     }
 67     node *new_node() {
 68         memset(mp[cnt].nd, 0x3f3f, sizeof(mp[cnt].nd));
 69         return &mp[cnt++];
 70     }
 71     void add(int w) {
 72         if (!pre->c[w]) pre->c[w] = new_node();
 73         pre = pre->c[w];
 74     }
 75     void danger() {
 76         pre->bad = 1;
 77     }
 78     void init() {
 79         pre = root;
 80     }
 81     void get_fail() {
 82         int h = 0, t = 0;
 83         node *p, *tmp;
 84         q[t++] = root;
 85         root->fail = NULL;
 86         while (h != t) {
 87             p = q[h++];
 88             rep0(i, 4) {
 89                 if (p->c[i]) {
 90                     if (p == root) p->c[i]->fail = root;
 91                     else {
 92                         tmp = p->fail;
 93                         while (tmp) {
 94                             if (tmp->c[i]) {
 95                                 p->c[i]->bad |= tmp->c[i]->bad;
 96                                 p->c[i]->fail = tmp->c[i];
 97                                 break;
 98                             }
 99                             tmp = tmp->fail;
100                         }
101                         if (!tmp) p->c[i]->fail = root;
102                     }
103                     q[t++] = p->c[i];
104                 }
105                 else {
106                     p->c[i] = p->fail&&p->fail->c[i] ? p->fail->c[i] : root;
107                 }
108             }
109         }
110     }
111     void solve(char *s) {
112         int l = strlen(s);
113         root->nd[0] = 0;
114         rep0(i, l) {
115             rep0(j, cnt) {
116                 if (mp[j].nd[i] != INF) {
117                     rep0(k, 4) {
118                         node *p = mp[j].c[k];
119                         if (!p || p->bad) continue;
120                         p->nd[i + 1] = min(p->nd[i + 1], mp[j].nd[i] + ((toint(s[i]) == k) ? 0 : 1));
121                     }
122                 }
123             }
124         }
125         int ans = INF;
126         rep0(i, cnt) {
127             if (!mp[i].bad) {
128                 ans = min(ans, mp[i].nd[l]);
129             }
130         }
131         printf("Case %d: %d\n", T, ans == INF ? -1 : ans);
132     }
133 } acm;
134 int read() {
135     char c = getchar(); int f = 1, x = 0;
136     while (!isdigit(c)) { if (c == '-') f = -1; c = getchar(); }
137     while (isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); }
138     return f * x;
139 }
140 char get_ch() {
141     char c = getchar();
142     while (!isalpha(c)) c = getchar();
143     return c;
144 }
145 
146 void get_input();
147 void work();
148 int main() {
149     freopen("in.txt", "r", stdin);
150     freopen("out.wa", "w", stdout);
151     while (++T) {
152         scanf("%d", &n);
153         if (!n) break;
154         acm.clear();
155         get_input();
156         work();
157     }
158     return 0;
159 }
160 void work() {
161     acm.solve(s);
162 }
163 void get_input() {
164     rep0(i, n) {
165         scanf("%s", s);
166         int l = strlen(s);
167         rep0(j, l) acm.add(toint(s[j]));
168         acm.danger();
169         acm.init();
170     }
171     acm.get_fail();
172     scanf("%s", s);
173 }

 

posted @ 2017-04-21 20:34  LoveYayoi  阅读(158)  评论(0编辑  收藏  举报