Lost's revenge HDU - 3341 AC自动机+DP(需要学会如何优雅的压缩状态)

Posted qldabiaoge

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Lost's revenge HDU - 3341 AC自动机+DP(需要学会如何优雅的压缩状态)相关的知识,希望对你有一定的参考价值。

题意:

给你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 
View Code

 

以上是关于Lost's revenge HDU - 3341 AC自动机+DP(需要学会如何优雅的压缩状态)的主要内容,如果未能解决你的问题,请参考以下文章

L - Lost's revenge HDU - 3341 (AC自动机 + 记忆化搜索 + 变进制算法)

HDU3341 Lost's revenge(AC自动机+DP)

Lost's revenge HDU - 3341 AC自动机+DP(需要学会如何优雅的压缩状态)

HDU 3341 Lost's revenge ( Trie图 && 状压DP && 数量限制类型 )

HDOJ3341Lost's revenge(AC自动机,DP)

●HDU 4787 GRE Words Revenge