HDU 4057 AC自动机+状压dp
2017-09-07 11:26
465 查看
题意:
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4057要求构造一条长度为l的字符串,构造的字符串中若含有给出的子串,就可以加上该子串的权值,但是同一子串只能算一次权值,问构造的字符串最大权值多少。
思路:
看到n只有10,典型的AC自动机状压的思路,dp[x][y][S]保存构造到第x个字符,到达结点y,且含有子串的状态为S是否可能,直接转移最后统计各种S下的最大权值即可。代码:
#include <bits/stdc++.h> using namespace std; const int INF = 0x3f3f3f3f; struct ACauto { int next[1005][4], fail[1005], end[1005]; int root, sz; int newnode() { for (int i = 0; i < 4; i++) next[sz][i] = -1; end[sz++] = 0; return sz - 1; } void init() { sz = 0; root = newnode(); } int idx(char c) { if (c == 'A') return 0; if (c == 'C') return 1; if (c == 'G') return 2; return 3; } void insert(char *buf, int id) { int len = strlen(buf); int now = root; for (int i = 0; i < len; i++) { int id = idx(buf[i]); if (next[now][id] == -1) next[now][id] = newnode(); now = next[now][id]; } end[now] |= (1 << id); } void build() { queue <int> Q; fail[root] = root; for (int i = 0; i < 4; i++) { if (next[root][i] == -1) next[root][i] = root; else { fail[next[root][i]] = root; Q.push(next[root][i]); } } while (!Q.empty()) { int now = Q.front(); Q.pop(); end[now] |= end[fail[now]]; for (int i = 0; i < 4; i++) { if (next[now][i] == -1) next[now][i] = next[fail[now]][i]; else { fail[next[now][i]] = next[fail[now]][i]; Q.push(next[now][i]); } } } } } ac; int n, len; bool dp[2][1005][1100]; int val[1100], v[15]; const char d[] = {'A', 'C', 'G', 'T'}; void solve() { for (int S = 0; S < (1 << n); S++) { val[S] = 0; for (int i = 0; i < n; i++) { if (S & (1 << i)) val[S] += v[i]; } } memset(dp, false, sizeof(dp)); dp[0][0][0] = true; for (int i = 0; i < len; i++) { for (int j = 0; j < ac.sz; j++) for (int S = 0; S < (1 << n); S++) dp[(i + 1) % 2][j][S] = false; for (int j = 0; j < ac.sz; j++) { for (int S = 0; S < (1 << n); S++) { if (!dp[i % 2][j][S]) continue; for (int k = 0; k < 4; k++) { int ni = i + 1, nj = ac.next[j][k], nS = S | ac.end[nj]; dp[ni % 2][nj][nS] |= dp[i % 2][j][S]; } } } } int ans = -INF; for (int j = 0; j < ac.sz; j++) { for (int S = 0; S < (1 << n); S++) { if (dp[len % 2][j][S]) ans = max(ans, val[S]); } } if (ans < 0) puts("No Rabbit after 2012!"); else printf("%d\n", ans); } char str[1005]; int main() { //freopen("in.txt", "r", stdin); while (scanf("%d%d", &n, &len) == 2) { ac.init(); for (int i = 0; i < n; i++) { scanf("%s%d", str, &v[i]); ac.insert(str, i); } ac.build(); solve(); } return 0; }
相关文章推荐
- hdu 4057 Rescue the Rabbit(AC自动机+状压dp)
- HDU 4057 Rescue the Rabbit 【AC自动机+状压DP】
- HDU 3247 AC自动机+状压DP
- HDU 6086 Rikka with String (AC 自动机+状压 dp, 2017 Multi-Univ Training Contest 5)
- HDU 2825 Wireless Password(AC自动机+状压DP)
- hdu_2825_Wireless Password(AC自动机+状压DP)
- HDU 2825 AC自动机+状压DP
- HDU 4057 Rescue the Rabbit(AC自动机+状态压缩dp)
- hdu 2825 Wireless Password (ac自动机+状压dp)
- [AC自动机+状压dp] hdu 4534 郑厂长系列故事——新闻净化
- HDU 4758 AC自动机+状压dp
- hdu 3247 Resource Archiver(AC自动机+状压DP)
- HDU 4057 Rescue the Rabbit(AC自动机+DP)
- Hdu 4057 Rescue the Rabbit (AC自动机+状态压缩dp) - 2011 ACM-ICPC Dalian Regional Contest Problem G
- hdu 6086 Rikka with String(AC自动机+状压dp)
- hdu 4057(ac自动机+状态压缩dp)
- hdu 2825 Wireless Password(AC自动机+状压DP)
- HDU 4057 Rescue the Rabbit(11年大连,AC自动机+状态压缩DP)
- HDU 2825(Wireless Password-AC自动机+状压dp)
- HDU 2825 Wireless Password && AC自动机+状压DP