题意:
给你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 }
