POJ 3691 DNA repair (AC自動機 + dp)

_TCgogogo_發表於2015-11-24
DNA repair
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 6014   Accepted: 2820

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 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

For 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 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


題目連結:http://poj.org/problem?id=3691


題目大意:給一些壞的字串,要求主串中不出現壞的字串,問最少要改變幾個主串中的字元


題目分析:將問題變為在 AC機上走(不走過危險結點),使得走過的路徑得到的串與目標串匹配最多,建AC機的時候如果一個點失敗指標指的點是壞點,那它也是壞點,相當於這個壞字串是另一個的子串,這裡還需要用Trie圖優化,方便dp時候狀態的轉移,dp[i][j]表示主串匹配了前i個字元且自動機在j結點時最少要改變的字元數,注意dp的時候要避開壞點

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
int const MAX = 1005;
int const INF = 1 << 30;
char s[50], t[MAX];

struct AC_DP
{
	int tot, root, fail[MAX], next[MAX][4];
	int dp[MAX][MAX];
	bool bad[MAX];

	inline int chg(char ch)
	{
		if(ch == 'A')
			return 0;
		if(ch == 'T')
			return 1;
		if(ch == 'C')
			return 2;
		return 3;
	}

	inline int Newnode()
	{
		for(int i = 0; i < 4; i++)
			next[tot][i] = -1;
		fail[tot] = 0;
		bad[tot] = false;
		return tot ++;
	}

	inline void Init()
	{
		tot = 0;
		root = Newnode();
	}

	inline void Insert(char *s)
	{
		int len = strlen(s);
		int p = root;
		for(int i = 0; i < len; i++)
		{
			int idx = chg(s[i]);
			if(next[p][idx] == -1)
				next[p][idx] = Newnode();
			p = next[p][idx];
		}
		bad[p] = true;
	}

	inline void Build()
	{
		queue <int> q;
		q.push(root);
		while(!q.empty())
		{
			int p = q.front();
			q.pop();
			for(int i = 0; i < 4; i++)
			{
				if(next[p][i] == -1)
				{
					if(p == root)
						next[p][i] = root;
					else
						next[p][i] = next[fail[p]][i];
				}
				else
				{
					if(p == root)
						fail[next[p][i]] = root;
					else
					{
						fail[next[p][i]] = next[fail[p]][i];
						bad[p] |= bad[fail[p]];
					}
					q.push(next[p][i]);
				}
			}
		}
	}

	inline int DP()
	{
		int tlen = strlen(t);
		int ans = INF;
		for(int i = 0; i <= tlen; i++)
			for(int j = 0; j < tot; j++)
				dp[i][j] = INF;
		dp[0][0] = 0;
		for(int i = 1; i <= tlen; i++)
			for(int j = 0; j < tot; j++)
				if(dp[i - 1][j] < INF)
					for(int k = 0; k < 4; k++)
						if(!bad[next[j][k]])
							dp[i][next[j][k]] = min(dp[i][next[j][k]], dp[i - 1][j] + (chg(t[i - 1]) != k));
		for(int j = 0; j < tot; j++)
			if(!bad[j])
				ans = min(ans, dp[tlen][j]);
		if(ans == INF)
			return -1;
		return ans;
	}	
}ac;

int main()
{
	int n, ca = 1;
	while(scanf("%d", &n) != EOF && n)
	{
		ac.Init();
		for(int i = 0; i < n; i++)
		{
			scanf("%s", s);
			ac.Insert(s);
		}
		scanf("%s", t);	
		ac.Build();
		printf("Case %d: %d\n", ca ++, ac.DP());
	}
}


相關文章