挺有意思的一道题目,解法是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. ###g++编译器

    点击查看Evernote原文. #@author: gr #@date: 2014-07-20 #@email: forgerui@gmail.com 对g++编译器不是特别熟悉,希望借此熟悉一下. ...

  2. Swift轻松入门——基本语法介绍和详细地Demo讲解(利用WebView打开百度、新浪等网页)

    转载请务必注明出处(all copyright reserved by iOSGeek) 本文主要分为两个部分,第一部分介绍Swift的基本语法,第二部分讲解一个利用WebView来打开百度.sina ...

  3. C#常量字段

    const 常量字段使用方法 using System;using System.Collections.Generic;using System.Linq;using System.Text;usi ...

  4. FlatBuffers

    1 What is FlatBuffers. FlatBuffers is a serialization library for games and other memory constrained ...

  5. 桶排序(BucketSort)

    1 桶排序核心思想是 根据数据规模n划分 m个相同大小的区间 (每个区间为一个桶,桶可理解为容器) 2 每个桶存储区间内的元素(区间为半开区间 例如[0,10) 或者 [200,300) ) 3 将n ...

  6. linux下查看端口的连接数

    linux下,可以通过natstat命令来查看端口的连接状况,比如连接数 例如,查看9090端口的连接状况: 查看某个端口的连接数netstat -nat | grep -iw "9090& ...

  7. 【HeadFirst设计模式】13.与设计模式相处

    模式: 是在某情境下,针对某问题的某种解决方案. 要点: 让设计模式自然而然地出现在你的设计中,而不是为了使用而使用. 设计模式并非僵化的教条,你可以依据自己的需要采用或者进行调整. 总是使用最简单的 ...

  8. django引用static目录下的css,js文件304问题

    前提:django1.8 在html页面可以请求道css,js文件并在chrome的开发者工具中查看css,js文件返回状态为200 原因: html页面在头部添加了<!DOCTYPE html ...

  9. How to fix “Duplicate sources.list entry …” issue

    The correct format of repository source line is <type of repository>  <location>  <di ...

  10. hdu 1695 GCD 莫比乌斯反演入门

    GCD 题意:输入5个数a,b,c,d,k;(a = c = 1, 0 < b,d,k <= 100000);问有多少对a <= p <= b, c <= q <= ...