zoukankan      html  css  js  c++  java
  • HDU 4057:Rescue the Rabbit(AC自动机+状压DP)***

    http://acm.hdu.edu.cn/showproblem.php?pid=4057

    题意:给出n个子串,串只包含‘A’,'C','G','T'四种字符,你现在需要构造出一个长度为l的串,如果这个串里面包含了某个子串,那么答案就会+val[i](如果这个串被使用过了,就不会再有贡献了),要使得构造出来的串的答案最大,问是多少。

    思路:只能想到是AC自动机的题目,然后乱搞出一个错误的方法,没想到是这样的操作。

    n只有10,因此才1024,开一个dp[l][sz][st]的数组,l代表当前的字符串长度,sz代表当前遍历的结点,st代表当前的状态(二进制表示使用了哪些字符串),这里的长度用滚动数组优化。

    方程:dp[now][nxt[j][x]][k|val[nxt[j][x]]] = dp[pre][j][k]; (当且仅当dp[pre][j][k]状态可取)

    nxt[j][x]代表j结点的下一个状态,val[now]代表now这个结点是哪个字符串的终点,因此k|val[nxt[j][x]]就是当前拥有的字符串的状态+下一个结点拥有的字符串的状态。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <queue>
     5 using namespace std;
     6 #define N 1010
     7 #define INF 0x3f3f3f3f
     8 int nxt[N][4], fail[N], val[N], rt, sz, n, l, num[11];
     9 bool dp[2][N][(1<<10)+10];
    10 char s[105];
    11 int newnode() {
    12     for(int i = 0; i < 4; i++) nxt[sz][i] = -1;
    13     val[sz++] = 0;
    14     return sz - 1;
    15 }
    16 void init() {
    17     sz = 0; rt = newnode();
    18 }
    19 int Turn(char c) {
    20     if(c == 'A') return 0;
    21     if(c == 'C') return 1;
    22     if(c == 'G') return 2;
    23     return 3;
    24 }
    25 void Insert(int id) {
    26     int len = strlen(s);
    27     int now = rt;
    28     for(int i = 0; i < len; i++) {
    29         int c = Turn(s[i]);
    30         if(nxt[now][c] == -1) nxt[now][c] = newnode();
    31         now = nxt[now][c];
    32     }
    33     val[now] |= (1 << id);
    34 }
    35 void Build() {
    36     queue<int> que;
    37     while(!que.empty()) que.pop();
    38     fail[rt] = rt;
    39     for(int i = 0; i < 4; i++) {
    40         if(nxt[rt][i] == -1) nxt[rt][i] = rt;
    41         else fail[nxt[rt][i]] = rt, que.push(nxt[rt][i]);
    42     }
    43     while(!que.empty()) {
    44         int now = que.front(); que.pop();
    45         val[now] |= val[fail[now]]; // 如果fail指向的结点是有状态的,应该加上!!!
    46         for(int i = 0; i < 4; i++) {
    47             if(nxt[now][i] == -1) nxt[now][i] = nxt[fail[now]][i];
    48             else fail[nxt[now][i]] = nxt[fail[now]][i], que.push(nxt[now][i]);
    49         }
    50     }
    51 }
    52 void Solve() {
    53     int pre = 0, now = 1;
    54     memset(dp, 0, sizeof(dp));
    55     dp[pre][0][0] = 1;
    56     for(int i = 0; i < l; i++) {
    57         memset(dp[now], 0, sizeof(dp[now]));
    58         for(int j = 0; j < sz; j++) {
    59             for(int k = 0; k < (1 << n); k++) {
    60                 if(!dp[pre][j][k]) continue;
    61                 for(int x = 0; x < 4; x++) {
    62                     dp[now][nxt[j][x]][k|val[nxt[j][x]]] = dp[pre][j][k]; // 哪些状态可以取
    63                     // nxt[j][x] 下一个结点
    64                     // k | val[nxt[j][x]] 当前状态加上下一个结点有的状态
    65                 }
    66             }
    67         }
    68         swap(now, pre);
    69     }
    70     int ans = -INF, res; now = l % 2;
    71     for(int i = 0; i < sz; i++) {
    72         for(int j = 0; j < (1 << n); j++) {
    73             if(!dp[now][i][j]) continue;
    74             res = 0;
    75             for(int k = 0; k < n; k++)
    76                 if(j & (1 << k)) res += num[k];
    77             ans = ans > res ? ans : res;
    78         }
    79     }
    80     if(ans >= 0) printf("%d
    ", ans);
    81     else puts("No Rabbit after 2012!");
    82 }
    83 
    84 int main() {
    85     while(~scanf("%d%d", &n, &l)) {
    86         init();
    87         for(int i = 0; i < n; i++) scanf("%s %d", s, &num[i]), Insert(i);
    88         Build();
    89         Solve();
    90     }
    91     return 0;
    92 }
    93 
    94 /*
    95 3 2
    96 A -1
    97 G -1
    98 C -1
    99 */
  • 相关阅读:
    (转)Docker network命令
    (转)Navicat连接MySQL8.0亲测有效
    (转)Docker 网络
    Docker问题方案收集
    (转)docker run的--rm选项详解
    (转)docker-compose安装
    (转)教你分分钟搞定Docker私有仓库Registry
    (转)Docker入门——Dockerfile详解
    (转)Windows下安装Docker, GitBash环境配置
    (转)教你分分钟搞定Docker私有仓库Registry
  • 原文地址:https://www.cnblogs.com/fightfordream/p/6828651.html
Copyright © 2011-2022 走看看