题目大意:给你N个DNA的串,也就是至包含‘A‘,‘T‘,‘G‘,‘C‘四种碱基的,这些给定的串都是带有遗传病的,然后给你一个不会超过1000的串,问你至少几个地方才能让这个串不包含遗传病,如果不论怎么修改都没用,输出‘-1‘
分析:用dp[Ni][nNode],表示长度为i时候到达第n个节点修改的最小次数,然后统计最后一层次最小次数就行了。
代码如下:
=============================================================================================================================
#include<iostream> #include<algorithm> #include<stdio.h> #include<string.h> #include<queue> using namespace std; const int MAXN = 1007; const int MAXM = 57; const int MaxSon = 4; const int oo = 1e9+7; int dp[MAXN][MAXN]; struct Ac_Trie { int next[MAXN][MaxSon]; int Fail[MAXN], End[MAXN]; int cnt, root; int newnode() { for(int i=0; i<MaxSon; i++) next[cnt][i] = -1; Fail[cnt] = End[cnt] = false; return cnt++; } void InIt() { cnt = 0; root = newnode(); } int Find(char ch) { if(ch == ‘A‘)return 0; if(ch == ‘T‘)return 1; if(ch == ‘G‘)return 2; return 3; } void Insert(char s[]) { int now = root; for(int i=0; s[i]; i++) { int k = Find(s[i]); if(next[now][k] == -1) next[now][k] = newnode(); now = next[now][k]; } End[now] = true; } void GetFial() { queue<int>Q; int now = root; for(int i=0; i<MaxSon; i++) { if(next[now][i] == -1) next[now][i] = root; else { Fail[next[now][i]] = root; Q.push(next[now][i]); } } while(Q.size()) { now = Q.front(); Q.pop(); for(int i=0; i<MaxSon; i++) { if(next[now][i] == -1) next[now][i] = next[Fail[now]][i]; else { Fail[next[now][i]] = next[Fail[now]][i]; Q.push(next[now][i]); } } End[now] |= End[Fail[now]]; } } }; Ac_Trie ac; int main() { int N, t=1; while(scanf("%d", &N), N) { char s[MAXN]; ac.InIt(); for(int i=0; i<N; i++) { scanf("%s", s); ac.Insert(s); } ac.GetFial(); scanf("%s", s+1); N = strlen(s); for(int i=0; i<=N; i++) for(int j=0; j<ac.cnt; j++) dp[i][j] = oo; dp[0][0] = 0; for(int i=0; i<N-1; i++) for(int j=0; j<ac.cnt; j++) for(int k=0; k<4; k++) { int w = dp[i][j]; int next = ac.next[j][k]; if(ac.End[next])continue; if(ac.Find(s[i+1]) != k) w++; if(dp[i+1][next] > w) dp[i+1][next] = w; } int Min = oo; for(int i=0; i<ac.cnt; i++) Min = min(Min, dp[N-1][i]); if(Min == oo) Min = -1; printf("Case %d: %d\n", t++, Min); } return 0; }
时间: 2024-10-10 06:59:57