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 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
number of characters which need to be changed. If it's impossible to repair the given DNA, print -1.
Sample Input
Sample Output
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 ", 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 }