题目大意:
给定一些不合理的DNA序列,再给一段较长的dna序列,问最少修改几次可以使序列中不存在任何不合理序列,不能找到修改方法输出-1
这里你修改某一个点的DNA可能会影响后面,我们不能单纯的找匹配数,因为你找到了你也不一定有方法改变它
这里用DP来解决
判断到第i位dna , 之前dp值保存了前面dna所能到达的所有状态:
dp[i][j] 也就是用了前i个dna所到达的状态至少需要修改的值
从所有状态出发,经过AGCT4种情况到达下一个状态,只要下一个状态不为非法状态即可
过程中只要判断你走的AGCT4种情况是否和当前字符相同,相同说明不用做出改变,即+0 , 否则+1,不断进行更新
1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 #include <vector> 5 #include <iostream> 6 #include <algorithm> 7 #include <map> 8 using namespace std; 9 #define clr(x) memset(x , 0 , sizeof(x)) 10 #define set(x) memset(x , -1 , sizeof(x)) 11 typedef long long LL ; 12 13 const int CHAR_SIZE = 4; 14 const int MAX_SIZE = 1005; 15 const int M = 10000 ; 16 int n,m,p; 17 int mp[256]; 18 19 struct AC_Machine{ 20 int ch[MAX_SIZE][CHAR_SIZE] , val[MAX_SIZE] , fail[MAX_SIZE]; 21 int sz; 22 23 void init(){ 24 sz = 1; 25 clr(ch[0]) , clr(val); 26 } 27 28 void insert(char *s){ 29 int n = strlen(s); 30 int u=0 ; 31 for(int i=0 ; i<n ; i++){ 32 int c = mp[s[i]]; 33 if(!ch[u][c]){ 34 clr(ch[sz]); 35 val[sz] = 0; 36 ch[u][c] = sz++; 37 } 38 u = ch[u][c]; 39 } 40 val[u] = 1; 41 } 42 43 void get_fail(){ 44 queue<int> Q; 45 fail[0] = 0; 46 for(int c=0 ; c<CHAR_SIZE ; c++){ 47 int u = ch[0][c]; 48 if(u){Q.push(u);fail[u]=0;} 49 } 50 while(!Q.empty()){ 51 int r = Q.front(); 52 Q.pop(); 53 val[r] |= val[fail[r]]; 54 for(int c=0 ; c<CHAR_SIZE ; c++){ 55 int u = ch[r][c]; 56 if(!u){ch[r][c] = ch[fail[r]][c]; continue;} 57 fail[u] = ch[fail[r]][c]; 58 Q.push(u); 59 } 60 } 61 } 62 }ac; 63 64 char str[1005]; 65 int f[1005][MAX_SIZE]; 66 int solve() 67 { 68 memset(f , 0x3f , sizeof(f)); 69 f[0][0] = 0; 70 int len = strlen(str) , ret=0x3f3f3f3f; 71 for(int i=1 ; i<=len ; i++){ 72 int v = mp[str[i-1]]; 73 for(int j=0 ; j<ac.sz ; j++){ 74 for(int k=0 ; k<CHAR_SIZE ; k++){ 75 if(!ac.val[ac.ch[j][k]]){ 76 f[i][ac.ch[j][k]] = min(f[i-1][j]+(v==k?0:1) , f[i][ac.ch[j][k]]); 77 } 78 } 79 } 80 } 81 for(int i=0 ; i<ac.sz ; i++){ 82 ret = min(ret , f[len][i]); 83 } 84 if(ret == 0x3f3f3f3f) return -1; 85 else return ret; 86 } 87 88 int main() 89 { 90 // freopen("in.txt" , "r" , stdin); 91 // freopen("out.txt" , "w" , stdout); 92 mp['A'] = 0 , mp['G'] = 1 , mp['C'] = 2 , mp['T'] = 3; 93 int cas = 0; 94 while(scanf("%d" , &n),n){ 95 ac.init(); 96 for(int i=1 ; i<=n ; i++){ 97 scanf("%s" , str); 98 ac.insert(str); 99 } 100 ac.get_fail(); 101 scanf("%s" , str); 102 printf("Case %d: " , ++cas); 103 printf("%d " , solve()); 104 } 105 return 0; 106 }