HDU - 3341 Lost's revenge(AC自己主动机+DP)

Description

Lost and AekdyCoin are friends. They always play "number game"(A boring game based on number theory) together. We all know that AekdyCoin is the man called "nuclear weapon of FZU,descendant of Jingrun", because of his talent in the
field of number theory. So Lost had never won the game. He was so ashamed and angry, but he didn‘t know how to improve his level of number theory.

One noon, when Lost was lying on the bed, the Spring Brother poster on the wall(Lost is a believer of Spring Brother) said hello to him! Spring Brother said, "I‘m Spring Brother, and I saw AekdyCoin shames you again and again. I can‘t bear my believers were
being bullied. Now, I give you a chance to rearrange your gene sequences to defeat AekdyCoin!".

It‘s soooo crazy and unbelievable to rearrange the gene sequences, but Lost has no choice. He knows some genes called "number theory gene" will affect one "level of number theory". And two of the same kind of gene in different position in the gene sequences
will affect two "level of number theory", even though they overlap each other. There is nothing but revenge in his mind. So he needs you help to calculate the most "level of number theory" after rearrangement.

Input

There are less than 30 testcases.

For each testcase, first line is number of "number theory gene" N(1<=N<=50). N=0 denotes the end of the input file.

Next N lines means the "number theory gene", and the length of every "number theory gene" is no more than 10.

The last line is Lost‘s gene sequences, its length is also less or equal 40.

All genes and gene sequences are only contains capital letter ACGT.

Output

For each testcase, output the case number(start with 1) and the most "level of number theory" with format like the sample output.

Sample Input

 3
AC
CG
GT
CGAT
1
AA
AAA
0 

Sample Output

 Case 1: 3
Case 2: 2 

题意:给你n个子串和一个母串,让你重排母串最多能得到多少个子串。

思路:如果ACGT的个数依次是num[0],num[1],num[2],num[3],将这四个数压缩成一个数,降低内存,然后动归dp[i][status]表示到自己主动机上i状态此时ACGT个数的状态时的最少

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int inf = 0x3f3f3f3f;

struct Trie {
	int nxt[510][4], fail[510], end[510];
	int root, cnt;

	int newNode() {
		for (int i = 0; i < 4; i++)
			nxt[cnt][i] = -1;
		end[cnt++] = 0;
		return cnt - 1;
	}
	void init() {
		cnt = 0;
		root = newNode();
	}
	int getch(char ch) {
		if (ch == ‘A‘) return 0;
		else if (ch == ‘C‘) return 1;
		else if (ch == ‘G‘) return 2;
		return 3;
	}
	void insert(char str[]) {
		int len = strlen(str);
		int now = root;
		for (int i = 0; i < len; i++) {
			if (nxt[now][getch(str[i])] == -1)
				nxt[now][getch(str[i])] = newNode();
			now = nxt[now][getch(str[i])];
		}
		end[now]++;
	}
	void build() {
		queue<int> q;
		fail[root] = root;
		for (int i = 0; i < 4; i++) {
			if (nxt[root][i] == -1)
				nxt[root][i] = root;
			else {
				fail[nxt[root][i]] = root;
				q.push(nxt[root][i]);
			}
		}

		while (!q.empty()) {
			int now = q.front();
			q.pop();
			end[now] += end[fail[now]]; //好像每次都是这里
			for (int i = 0; i < 4; i++) {
				if (nxt[now][i] == -1)
					nxt[now][i] = nxt[fail[now]][i];
				else {
					fail[nxt[now][i]] = nxt[fail[now]][i];
					q.push(nxt[now][i]);
				}
			}
		}
	}
	int dp[510][11*11*11*11+5];
	int bit[4], num[4];
	int solve(char str[]) {
		int len = strlen(str);
		memset(num, 0, sizeof(num));
		for (int i = 0; i < len; i++)
			num[getch(str[i])]++;
		bit[0] = (num[1]+1) * (num[2]+1) * (num[3]+1);
		bit[1] = (num[2]+1) * (num[3]+1);
		bit[2] = (num[3]+1);
		bit[3] = 1;
		memset(dp, -1, sizeof(dp));
		dp[root][0] = 0;
		for (int A = 0; A <= num[0]; A++)
			for (int B = 0; B <= num[1]; B++)
				for (int C = 0; C <= num[2]; C++)
					for (int D = 0; D <= num[3]; D++) {
						int s = A * bit[0] + B * bit[1] + C * bit[2] + D * bit[3];
						for (int i = 0; i < cnt; i++)
							if (dp[i][s] >= 0) {
								for (int k = 0; k < 4; k++) {
									if (k == 0 && A == num[0]) continue;
									if (k == 1 && B == num[1]) continue;
									if (k == 2 && C == num[2]) continue;
									if (k == 3 && D == num[3]) continue;
									dp[nxt[i][k]][s+bit[k]] = max(dp[nxt[i][k]][s+bit[k]], dp[i][s]+end[nxt[i][k]]);
								}
							}
					}

		int ans = 0;
		int status = num[0] * bit[0] + num[1] * bit[1] + num[2] * bit[2] + num[3] * bit[3];
		for (int i = 0; i < cnt; i++)
			ans = max(ans, dp[i][status]);
		return ans;
	}
} ac;
char str[50];

int main() {
	int n, cas = 1;
	while (scanf("%d", &n) != EOF && n) {
		ac.init();
		for (int i = 0; i < n; i++) {
			scanf("%s", str);
			ac.insert(str);
		}

		ac.build();
		scanf("%s", str);
		printf("Case %d: %d\n", cas++, ac.solve(str));
	}
	return 0;
}

HDU - 3341 Lost's revenge(AC自己主动机+DP)

时间: 2024-12-24 13:27:16

HDU - 3341 Lost&#39;s revenge(AC自己主动机+DP)的相关文章

HDU - 4758 Walk Through Squares (AC自己主动机+DP)

Description On the beaming day of 60th anniversary of NJUST, as a military college which was Second Artillery Academy of Harbin Military Engineering Institute before, queue phalanx is a special landscape. Here is a M*N rectangle, and this one can be

hdu4758 Walk Through Squares (AC自己主动机+DP)

Walk Through Squares Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others) Total Submission(s): 944 Accepted Submission(s): 277 Problem Description On the beaming day of 60th anniversary of NJUST, as a military college whic

Zoj 3535 Gao the String II (AC自己主动机+dp)

题目大意: 用集合A中的串构造出一个串,使之让很多其它的setB中的串成为他的子串. 思路分析: 和 Codeforces 86C 几乎相同. 只是这里是要用A中的构造. 先用A 和 B的串构造一个自己主动机.然后对于A集合的尾结点给出一个最大后缀匹配,对于B集合的尾结点给一个权值. dp[i][j][k] 表示已经构造出来了一个长度为i的串,如今走到了自己主动机的j结点.i长度后面有k个字符是没有匹配到的. 继续在自己主动机上走进行状态转移. if(isword >= k +1 )dp [i+

hdu 3056 病毒侵袭持续中 AC自己主动机

http://acm.hdu.edu.cn/showproblem.php?pid=3065 刘汝佳的模板真的非常好用,这道题直接过 学到: cnt数组记录单词出现次数 以及map存储单词编号与字符串,便于处理相关信息 上代码: #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <queue> #include <st

Zoj 3545 Rescue the Rabbit(ac自己主动机+dp)

标题效果: 鉴于DNA有一个正确的顺序值.请构造一个长度I的DNA在这个序列使DNA正确的顺序值极大.它被认为是负的输出噼啪. .. IDEAS: 施工顺序是,ac己主动机上走,求最大要用到dp dp[i][j][k] 表示如今构造到了长度 i . 此时的我们把当前字符放在j节点.而且满足了k状态.k是一个10位的2进制状态压缩. 注意这道题上有坑就是一个序列可能有多个权值. 所以不能直接赋值.须要用位或. #include <cstdio> #include <iostream>

HDU 3341 Lost&#39;s revenge AC自动机+ 状态压缩DP

题意:这个题目和HDU2457有点类似,都是AC自动机上的状态dp,题意就是给你只含有'A','T','C','G',四个字符的子串和文本串,问你文本串如何排列才可以使得文本串中包含有更多的模式串 解题思路:我们知道了 有 num[0] 个 'A', num[1] 个 ‘T’, num[2] 个 ‘C’,num[3] 个‘G’, 我们的可以知道暴力的思路就是把所有的文本串都枚举出来然后一一匹配.我们膜拜了一下春哥以后,就可以有以下思路:  把一个串的信息压缩一下,把具有同样个数字符的串看成是同一

POJ 3691 &amp;amp; HDU 2457 DNA repair (AC自己主动机,DP)

http://poj.org/problem?id=3691 http://acm.hdu.edu.cn/showproblem.php?pid=2457 DNA repair Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5690   Accepted: 2669 Description Biologists finally invent techniques of repairing DNA that contain

hdu 2825 Wireless Password(ac自己主动机&amp;amp;dp)

Wireless Password Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4022    Accepted Submission(s): 1196 Problem Description Liyuan lives in a old apartment. One day, he suddenly found that there

HDU 2222 Keywords Search(AC自己主动机模板题)

题意:给出一个字符串和若干个模板,求出在文本串中出现的模板个数. 思路:由于有可能有反复的模板,trie树权值记录每一个模板出现的次数就可以. #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<iostream> #include<algorithm> #include<vector> #include<map&