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 Descriptionbiologists 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 is 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-characters. Note that the repaired DNA can still contain only characters ' A ', ' G ', ' C ' and ' T '.
The biologists to repair a DNA by changing least number of characters.
Inputthe 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 Inhe rited diseases.
The following n lines gives n non-empty strings of length not greater than all containing only characters in "AGCT", which is the DNA segments causing inherited disease.
The last line of the that test case is a non-empty string of length not greater than-containing only characters in "AGCT", Which is the DNA to be repaired.
The last test was followed by a line containing one zeros.
Outputfor 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 Input2aaaaagaaag 2ATGTGAATG 4AGCTAGT 0
Sample outputcase 1:1case 2:4case 3:1
/*hdu 2457 ac automaton +DP give you n substrings and a main string. The minimum number of modifications to the main string so that it does not contain a substring through an AC automaton capable of processing a state transition diagram with DP[I][J] represents the length of I, the current position is the smallest modification of J. NEX[J][K] Node number of State K if the current position is the same as the main string, you do not need to modify it, otherwise +1 and through the ED array we determine whether the current has reached the end of any substring. Then dp[i][nex[j][k]] = min (dp[i][nex[j][k]],dp[ I-1][j] + (k = = Str[i] 0:i)) hhh-2016-04-24 11:23:59*/#include <iostream> #include <vector> #include < cstring> #include <string> #include <cstdio> #include <queue> #include <algorithm> #include <functional> #include <map>using namespace std; #define Lson (i<<1) #define Rson ((i<<1) | | typedef unsigned long long ll;typedef unsigned int ul;const int INF = 0x3f3f3f3f;int tot;int dp[2][1010];//struct matrix// {//int len;//int ma[1010][1010];//matrix () {}//matrix (int L)//{//len = l;//}//};struct Tir e{int nex[1010][4],fail[1010],ed[1010]; int root,l; int NewNode () {for (int i = 0; i < 4; i++) nex[l][i] = 1; ed[l++] = 0; return L-1; } void INI () {L = 0,root = NewNode (); } int cal (char ch) {if (ch = = ' A ') return 0; else if (ch = = ' C ') return 1; else if (ch = = ' G ') return 2; else if (ch = = ' T ') return 3; } void Inser (char buf[]) {int len = strlen (BUF); int now = root; for (int i = 0; i < len; i++) {int ta = cal (Buf[i]); if (nex[now][ta] = =-1) nex[now][ta] = NewNode (); now = Nex[now][ta]; } Ed[now] + +; } void Build () {Queue<int >q; Fail[root] = root; for (int i = 0; i < 4; i++) if (nex[root][i] = = 1) nex[root][i] = root; else {Fail[nex[root][i]] = root; Q.push (Nex[root][i]); } while (!q.empty ()) {Int. now = Q.front (); Q.pop (); if (Ed[fail[now]]) Ed[Now] = 1; for (int i = 0; i < 4; i++) {if (nex[now][i] = = 1) nex[now][i] = nex[fail[ Now]][i]; else {Fail[nex[now][i]] = nex[fail[now]][i]; Q.push (Nex[now][i]); }}}}//Matrix To_mat ()//{//Matrix mat (L);//Memset (mat.ma,0,sizeof (mat.ma)); for (int i = 0; i < L; i++)//{//for (int j = 0; J < 4; j + +)//{// if (!ed[nex[i][j]])//MAT.MA[I][NEX[I][J]] ++;//}//}//return mat;//} };//matrix Mat; Tire Ac;char Str[1100];char buf[22];int main () {int n; int cas = 1; while (scanf ("%d", &n)! = EOF && N) {Ac.ini (); for (int i = 1; I <= n; i++) {scanf ("%s", buf); Ac.inser (BUF); } ac.build ();//Mat = Ac.to_mat (); For (int i = 0; I < AC. L i++) Dp[0][i] = INF; Dp[0][0] = 0; int cur = 0; scanf ("%s", str); for (int i = 0; i < (int) strlen (str); i++) {cur ^= 1; for (int i = 0; i < AC. L i++) Dp[cur][i] = INF; for (int j = 0; J < AC. L J + +) {for (int k = 0; k < 4; k++) {if (dp[cur^1][j]! = INF &&!ac.ed[ac.nex[j][k]]) dp[cur][ac.nex[j][k] [min (Dp[cur][ac.nex[j][k]], Dp[cur^1][j] + (k = = Ac.cal (Str[i])? 0:1)); }}} int ans = INF; for (int i = 0; i < AC. L i++) ans = min (ans,dp[cur][i]); printf ("Case%d:", cas++); if (ans = = INF) cout <<-1 << "\ n"; else cout << ans << "\ n"; } return 0;}
HDU 2457 AC automatic machine +DP