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 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
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
Source
2008 Asia Hefei Regional Contest Online by USTC
題意:
給定N個模式串(1 ≤ N ≤ 50) 最大長度為20,一個主串(長最大為1000),允許涉及的字符為4個 {'A','T','G','C'},求最少修改幾個字符 使主串不包含所有模式串。
思路:
對模式串建立AC自動機,根據AC自動機來dp。
dp[i][j]表示到主串第i個字符時到達自動機上第j個節點時修改最少字符數。
枚舉下一個字符為AGCT中的一個來轉移,注意轉移的時候不能包含模式串中的節點,於是要用一個數組來記錄該節點結尾時是否包含了單詞。
代碼:
#include#include #include #include #include using namespace std; const int INF=0x3f3f3f3f; const int maxn=10010; const int bsz=26; typedef long long ll; char txt[maxn],cc[]="AGCT"; bool vis[maxn]; int ans; struct Trie { bool have[maxn]; // 該節點結尾是否包含單詞 int ch[maxn][bsz],val[maxn],sz,cnt[maxn]; // ch存Trie val-節點對應的單詞 cnt-節點結尾單詞個數 int f[maxn],last[maxn];//f-失配指針 last-後綴鏈接 int newnode() { val[sz]=0; cnt[sz]=0; have[sz]=0; memset(ch[sz],-1,sizeof ch[sz]); return sz++; } void init() { sz=0; newnode(); } int idx(char c) // 取c的標號 具體看字符為什麼 { return c-'A'; } void Insert(char *st,int id) { int u=0,n=strlen(st),c,i; for(i=0;i q; f[0]=0; for(i=0;i =INF) continue ; for(k=0;k<4;k++) { id=ac.idx(cc[k]); next=ac.ch[j][id]; if(ac.have[next]) continue ; if(cc[k]==txt[i+1]) { dp[i+1][next]=min(dp[i+1][next],dp[i][j]); } else { dp[i+1][next]=min(dp[i+1][next],dp[i][j]+1); } } } } ans=INF; for(j=0;j=INF) ans=-1; } int main() { int i,j,n,ca=0; while(~scanf("%d",&n)) { if(n==0) break ; ac.init(); for(i=1;i<=n;i++) { scanf("%s",txt); ac.Insert(txt,i); } ac.build(); scanf("%s",txt+1); solve(); printf("Case %d: %d\n",++ca,ans); } return 0; }