挺有意思的一道题目,解法是AC自动机+DP。
AC自动机建立fail指针时,一定要注意结点的属性也需要传递。AC自动机结合了trie和kmp的优点。
需要注意的是,每个模式串仅计算一次,否则这题很难解。

 /* 4057 */
#include <iostream>
#include <sstream>
#include <string>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#include <deque>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstring>
#include <climits>
#include <cctype>
#include <cassert>
#include <functional>
#include <iterator>
#include <iomanip>
using namespace std;
//#pragma comment(linker,"/STACK:102400000,1024000") #define sti set<int>
#define stpii set<pair<int, int> >
#define mpii map<int,int>
#define vi vector<int>
#define pii pair<int,int>
#define vpii vector<pair<int,int> >
#define rep(i, a, n) for (int i=a;i<n;++i)
#define per(i, a, n) for (int i=n-1;i>=a;--i)
#define clr clear
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define lson l, mid, rt<<1
#define rson mid+1, r, rt<<1|1 const int maxn = ;
const int maxm = ;
const int maxl = ;
char s[maxl];
int W[maxn];
bool dp[][maxm][maxm];
int n, m, l; typedef struct {
static const int maxn = ;
static const int rt = ;
int nxt[maxn][];
int fail[maxn];
int f[maxn];
int m; void init() {
m = ;
memset(f, , sizeof(f));
memset(nxt, , sizeof(nxt));
} int newNode() {
return ++m;
} int getId(char c) {
if (c == 'A') return ;
if (c == 'T') return ;
if (c == 'G') return ;
if (c == 'C') return ;
return -;
} void Insert(char *s, int k) {
int i = , id;
int p = , q; while (s[i]) {
id = getId(s[i]);
q = nxt[p][id];
if (!q)
q = nxt[p][id] = newNode();
p = q;
++i;
}
f[p] |= ( << k);
} void Build() {
int cur;
queue<int> Q; fail[rt] = rt;
rep(i, , ) {
if (nxt[rt][i] == ) {
nxt[rt][i] = rt;
} else {
fail[nxt[rt][i]] = rt;
Q.push(nxt[rt][i]);
}
} while (!Q.empty()) {
cur = Q.front();
Q.pop();
rep(i, , ) {
if (nxt[cur][i] == ) {
nxt[cur][i] = nxt[fail[cur]][i];
} else {
fail[nxt[cur][i]] = nxt[fail[cur]][i];
f[nxt[cur][i]] |= f[nxt[fail[cur]][i]];
Q.push(nxt[cur][i]);
}
}
}
} } AC; AC ac; int calw(int x) {
int ret = ; rep(i, , n) {
if (x & (<<i))
ret += W[i];
} return ret;
} void solve() {
int ans = INT_MIN;
int mst = <<n, nst, nxt;
int p = , q = ; m = ac.m;
memset(dp, , sizeof(dp));
dp[][ac.rt][] = true;
rep(i, , l+) {
memset(dp[q], , sizeof(dp[q]));
rep(j, , m+) {
rep(k, , ) {
rep(st, , mst) {
if (dp[p][j][st]) {
nxt = ac.nxt[j][k];
nst = st | ac.f[nxt];
dp[q][nxt][nst] = true;
}
}
}
}
p = q;
q ^= ;
} rep(st, , mst) {
rep(j, , m+) {
if (dp[p][j][st]) {
ans = max(ans, calw(st));
break;
}
}
} if (ans < )
puts("No Rabbit after 2012!");
else
printf("%d\n", ans);
} int main() {
ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
#endif int len, w; while (scanf("%d %d",&n,&l) != EOF) {
ac.init();
rep(i, , n) {
scanf("%s %d", s, &W[i]);
ac.Insert(s, i);
} ac.Build();
solve();
} #ifndef ONLINE_JUDGE
printf("time = %d.\n", (int)clock());
#endif return ;
}

【HDOJ】4057 Rescue the Rabbit的更多相关文章

  1. 【HDOJ】1222 Wolf and Rabbit

    最大公约数,辗转相除. #include <stdio.h> long long gcd(long long a, long long b) { if (a<b) return gc ...

  2. 【HDOJ】1242 Rescue

    BFS+优先级队列. #include <iostream> #include <cstdio> #include <cstring> #include <q ...

  3. 【HDOJ】4729 An Easy Problem for Elfness

    其实是求树上的路径间的数据第K大的题目.果断主席树 + LCA.初始流量是这条路径上的最小值.若a<=b,显然直接为s->t建立pipe可以使流量最优:否则,对[0, 10**4]二分得到 ...

  4. HDU 4057 Rescue the Rabbit(AC自动机+DP)

    题目链接 一个数组开小了一点点,一直提示wa,郁闷,这题比上个题简单一点. #include <iostream> #include <cstring> #include &l ...

  5. 【HDOJ】【3506】Monkey Party

    DP/四边形不等式 裸题环形石子合并…… 拆环为链即可 //HDOJ 3506 #include<cmath> #include<vector> #include<cst ...

  6. 【HDOJ】【3516】Tree Construction

    DP/四边形不等式 这题跟石子合并有点像…… dp[i][j]为将第 i 个点开始的 j 个点合并的最小代价. 易知有 dp[i][j]=min{dp[i][j] , dp[i][k-i+1]+dp[ ...

  7. 【HDOJ】【3480】Division

    DP/四边形不等式 要求将一个可重集S分成M个子集,求子集的极差的平方和最小是多少…… 首先我们先将这N个数排序,容易想到每个自己都对应着这个有序数组中的一段……而不会是互相穿插着= =因为交换一下明 ...

  8. 【HDOJ】【2829】Lawrence

    DP/四边形不等式 做过POJ 1739 邮局那道题后就很容易写出动规方程: dp[i][j]=min{dp[i-1][k]+w[k+1][j]}(表示前 j 个点分成 i 块的最小代价) $w(l, ...

  9. 【HDOJ】【3415】Max Sum of Max-K-sub-sequence

    DP/单调队列优化 呃……环形链求最大k子段和. 首先拆环为链求前缀和…… 然后单调队列吧<_<,裸题没啥好说的…… WA:为毛手写队列就会挂,必须用STL的deque?(写挂自己弱……s ...

随机推荐

  1. C# 多任务之 Task

    Task 是什么 ? Task 是一个类, 它表示一个操作不返回一个值,通常以异步方式执行. Task 对象是一个的中心思想 基于任务的异步模式 首次引入.NET Framework 4 中. 继承层 ...

  2. OpenJudge/Poj 1207 The 3n + 1 problem

    1.链接地址: http://bailian.openjudge.cn/practice/1207/ http://poj.org/problem?id=1207 2.题目: 总时间限制: 1000m ...

  3. 《jQuery、jQuery UI及jQuery Mobile技巧与示例》勘误收集

    此书由程学彬 (http://weibo.com/ironbin)和我合译完成,此篇博客作为勘误收集而用,若译文有误或者有任何疑问,欢迎留下评论,或者给我发邮件(地址:gzooler@gmail.co ...

  4. CentOS安装mplayer

    据说mplayer相当于windows下的暴风影音,那么今天就来安装上mplayer. 安装的大体步骤: 安装mplayer需要安装,解码器,mplayer,皮肤. 这三个包你都可以在mplayer官 ...

  5. Linux查看目录挂载点

    用命令 df 即可 # df /var/lib/ Filesystem 1K-blocks Used Available Use% Mounted on /dev/sda3 135979984 669 ...

  6. CentOS下shell显示-bash-4.1#不显示用户名路径的解决方法

    CentOS下shell显示-bash-4.1$不显示用户名路径的解决方法 问题描述: CentOS下新增一个用户,登录进去之后shell脚本的信息如下: 而不是我们经常看到的username@hos ...

  7. 一些web编程能用到的小知识

    1 信用卡验证算法-luhn算法.(in django/utils/checksums.py) 1.从卡号最后一位数字开始,逆向将奇数位(1.3.5等等)相加.2.将偶数位数字相加,但是这里有个麻烦. ...

  8. python函数的返回值 讲解

    我们一起来聊聊python函数返回值的特殊情况,之前我也碰到过类似方面的问题,到后来查阅了一些资料后,发现原来是这样. 首先,写函数的时候,一定要写函数的文档,这样方便我们识别函数是做什么的.我记得很 ...

  9. Java基础中的一些注意点(续)

    1.局部(local)变量是在一个方法内定义的变量, 也被称作自动(automatic).临时(temporary)或栈(stack)变量 -          当一个方法被执行时, 局部变量被创建: ...

  10. 刷漆(Codechef October Challenge 2014:Remy paints the fence)

    [问题描述] Czy做完了所有的回答出了所有的询问,结果是,他因为脑力消耗过大而变得更虚了:).帮助Czy恢复身材的艰巨任务落到了你的肩上. 正巧,你的花园里有一个由N块排成一条直线的木板组成的栅栏, ...