标签:子串和 roman str als ring text strlen cga main
Description
Input
Output
Sample Input
3 AC CG GT CGAT 1 AA AAA 0
Sample Output
Case 1: 3 Case 2: 2
思路:如果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)
标签:子串和 roman str als ring text strlen cga main
原文地址:http://www.cnblogs.com/llguanli/p/7152095.html