题意:
给你n个子串和一个母串,让你重排母串最多能得到多少个子串出现在重排后的母串中。
首先第一步肯定是获取母串中每个字母出现的次数,只有A T C G四种。
这个很容易想到一个dp状态dp【i】【A】【B】【C】【D】
表示在AC自动机 i 这个节点上,用了A个A,B个T,C个C,D个G。
然后我算了一下内存,根本开不下这么大的内存。
看了网上题解,然后用通过状压把,A,B,C,D压缩成一维。
这个状压就是通过进制实现需要实现唯一表示
bit[0] = 1;
bit[1] = (num[0] + 1);
bit[2] = (num[0] + 1) * (num[1] + 1);
bit[3] = (num[0] + 1) * (num[1] + 1) * (num[2] + 1);
这样就实现了A,B,C,D的唯一表示。
知道如何优化空间这题就变得非常简单了。
1 #include <set> 2 #include <map> 3 #include <stack> 4 #include <queue> 5 #include <cmath> 6 #include <ctime> 7 #include <cstdio> 8 #include <string> 9 #include <vector> 10 #include <cstring> 11 #include <iostream> 12 #include <algorithm> 13 #include <unordered_map> 14 15 #define pi acos(-1.0) 16 #define eps 1e-9 17 #define fi first 18 #define se second 19 #define rtl rt<<1 20 #define rtr rt<<1|1 21 #define bug printf("******\n") 22 #define mem(a, b) memset(a,b,sizeof(a)) 23 #define name2str(x) #x 24 #define fuck(x) cout<<#x" = "<<x<<endl 25 #define sfi(a) scanf("%d", &a) 26 #define sffi(a, b) scanf("%d %d", &a, &b) 27 #define sfffi(a, b, c) scanf("%d %d %d", &a, &b, &c) 28 #define sffffi(a, b, c, d) scanf("%d %d %d %d", &a, &b, &c, &d) 29 #define sfL(a) scanf("%lld", &a) 30 #define sffL(a, b) scanf("%lld %lld", &a, &b) 31 #define sfffL(a, b, c) scanf("%lld %lld %lld", &a, &b, &c) 32 #define sffffL(a, b, c, d) scanf("%lld %lld %lld %lld", &a, &b, &c, &d) 33 #define sfs(a) scanf("%s", a) 34 #define sffs(a, b) scanf("%s %s", a, b) 35 #define sfffs(a, b, c) scanf("%s %s %s", a, b, c) 36 #define sffffs(a, b, c, d) scanf("%s %s %s %s", a, b,c, d) 37 #define FIN freopen("../in.txt","r",stdin) 38 #define gcd(a, b) __gcd(a,b) 39 #define lowbit(x) x&-x 40 #define IO iOS::sync_with_stdio(false) 41 42 43 using namespace std; 44 typedef long long LL; 45 typedef unsigned long long ULL; 46 const ULL seed = 13331; 47 const LL INFLL = 0x3f3f3f3f3f3f3f3fLL; 48 const int maxn = 1e6 + 7; 49 const int maxm = 8e6 + 10; 50 const int INF = 0x3f3f3f3f; 51 const int mod = 1e9 + 7; 52 53 int n, dp[510][11 * 11 * 11 * 11 + 10], num[5], bit[5]; 54 char buf[50]; 55 56 int get_num(char ch) { 57 if (ch == ‘A‘) return 0; 58 if (ch == ‘T‘) return 1; 59 if (ch == ‘C‘) return 2; 60 if (ch == ‘G‘) return 3; 61 } 62 63 struct Aho_Corasick { 64 int next[510][4], fail[510], End[510]; 65 int root, cnt; 66 67 int newnode() { 68 for (int i = 0; i < 4; i++) next[cnt][i] = -1; 69 End[cnt++] = 0; 70 return cnt - 1; 71 } 72 73 void init() { 74 cnt = 0; 75 root = newnode(); 76 } 77 78 void insert(char buf[]) { 79 int len = strlen(buf); 80 int now = root; 81 for (int i = 0; i < len; i++) { 82 if (next[now][get_num(buf[i])] == -1) next[now][get_num(buf[i])] = newnode(); 83 now = next[now][get_num(buf[i])]; 84 } 85 End[now]++; 86 } 87 88 void build() { 89 queue<int> Q; 90 fail[root] = root; 91 for (int i = 0; i < 4; i++) 92 if (next[root][i] == -1) next[root][i] = root; 93 else { 94 fail[next[root][i]] = root; 95 Q.push(next[root][i]); 96 } 97 while (!Q.empty()) { 98 int now = Q.front(); 99 Q.pop(); 100 End[now] += End[fail[now]]; 101 for (int i = 0; i < 4; i++) 102 if (next[now][i] == -1) next[now][i] = next[fail[now]][i]; 103 else { 104 fail[next[now][i]] = next[fail[now]][i]; 105 Q.push(next[now][i]); 106 } 107 } 108 } 109 110 int solve(char buf[]) { 111 int len = strlen(buf); 112 mem(num, 0); 113 for (int i = 0; i < len; ++i) num[get_num(buf[i])]++; 114 bit[0] = 1; 115 bit[1] = (num[0] + 1); 116 bit[2] = (num[0] + 1) * (num[1] + 1); 117 bit[3] = (num[0] + 1) * (num[1] + 1) * (num[2] + 1); 118 mem(dp, -1); 119 dp[0][0] = 0; 120 for (int A = 0; A <= num[0]; ++A) { 121 for (int B = 0; B <= num[1]; ++B) { 122 for (int C = 0; C <= num[2]; ++C) { 123 for (int D = 0; D <= num[3]; ++D) { 124 for (int i = 0; i < cnt; ++i) { 125 int s = A * bit[0] + B * bit[1] + C * bit[2] + D * bit[3]; 126 if (dp[i][s] == -1) continue; 127 for (int k = 0; k < 4; ++k) { 128 if (k == 0 && A == num[0]) continue; 129 if (k == 1 && B == num[1]) continue; 130 if (k == 2 && C == num[2]) continue; 131 if (k == 3 && D == num[3]) continue; 132 int idx = next[i][k]; 133 dp[idx][s + bit[k]] = max(dp[idx][s + bit[k]], dp[i][s] + End[idx]); 134 } 135 } 136 } 137 } 138 } 139 } 140 int ans = 0, status = num[0] * bit[0] + num[1] * bit[1] + num[2] * bit[2] + num[3] * bit[3]; 141 for (int i = 0; i < cnt; ++i) ans = max(ans, dp[i][status]); 142 return ans; 143 } 144 145 146 void debug() { 147 for (int i = 0; i < cnt; i++) { 148 printf("id = %3d,fail = %3d,end = %3d,chi = [", i, fail[i], End[i]); 149 for (int j = 0; j < 26; j++) printf("%2d", next[i][j]); 150 printf("]\n"); 151 } 152 } 153 } ac; 154 155 int main() { 156 //FIN; 157 int cas = 1; 158 while (sfi(n) && n) { 159 ac.init(); 160 for (int i = 0; i < n; ++i) { 161 sfs(buf); 162 ac.insert(buf); 163 } 164 ac.build(); 165 sfs(buf); 166 printf("Case %d: %d\n", cas++, ac.solve(buf)); 167 } 168 return 0; 169 }
Lost's revenge HDU - 3341 AC自动机+DP(需要学会如何优雅的压缩状态)
原文地址:https://www.cnblogs.com/qldabiaoge/p/11379448.html
时间: 2024-10-09 21:15:22