挺有意思的一道题目,解法是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. Android-ViewPagerIndicator-master 、Android-PullToRefresh 学习篇

    最近在学习android,然后看到了很多有用的开源库.其中一个就是Android-ViewPagerIndicator :. 这是与ViewPager兼容的一个分页指示器库.分页指示器(Friends ...

  2. cache在spring中使用

    一:参考文章 (1)http://haohaoxuexi.iteye.com/blog/2123030  Spring使用Cache,这篇文章讲的比较详细. 注:本文是对参考文章和实际使用中经验的总结 ...

  3. apache 工作模式

    apache三种工作模式: prefork(2.4前默认)/worker/event(2.4默认)内容整理来自以下网站http://m.blog.csdn.net/article/details?id ...

  4. fedora 非root用户访问socket 没用权限

    在非root用户下执行基于Libpcap库编写的应用程序时不能正常运行,原因是由于libpcap库使用raw socket的套接字.而Raw Socket的使用需要root权限,否则raw socke ...

  5. PHP — 用PHP实现一个双向队列

    1.简介 deque,全名double-ended queue,是一种具有队列和栈的性质的数据结构.双端队列中的元素可以从两端弹出,其限定插入和删除操作在表的两端进行.双向队列(双端队列)就像是一个队 ...

  6. 使用内核定时器的second字符设备驱动及测试代码

    驱动: #include <linux/kernel.h> #include <linux/module.h> #include <linux/fs.h> #inc ...

  7. Maya QT interfaces in a class

    Most tutorials online have suggested the way to fire commands inside QT interfaces launched n Maya ( ...

  8. 调用windows api 获取系统分辨率

    c++中: int cxScreen,cyScreen; cxScreen=GetSystemMetrics(SM_CXSCREEN); cyScreen=GetSystemMetrics(SM_CY ...

  9. pywinauto简单介绍

    Pywinauto是基于Python开发的,用于自动化测试的脚本模块,主要操作于Windows标准图形界面.它可以允许你很容易的发送鼠标.键盘动作给Windows的对话框和控件. 其中,最主要功能为对 ...

  10. How To Call Stored Procedure In Hibernate

    How To Call Stored Procedure In Hibernate In this tutorial, you will learn how to call a store proce ...