HDU-4534 郑厂长系列故事——新闻净化 AC自动机+DP
题意:给定一些单词,这些单词必须要是一个目标串的子串,同时给定一些串,这些串不能够出现在目标串中,其余一些串只会带来不同附加值。现在问满足前两者的情况下,要求附加值最大。数据给定一个原始串,现在要求在这些串中删除一些字符,输出在满足要求的情况下删除最少的字符并保证附加值尽可能的大。
分析:这题的一个暴力的方法肯定就是对于每个字符枚举删或者不删,然后选择一种方案即可。在这个蛮力法的后面注意到其实在枚举的时候还是有很多重复计算的,比如前a个字符删除或者不删除某个字符对于后面的选择是一样的,而题目要求拥有所有的必有串,因此可以将所有的必有串建立一个ac自动机,然后根据枚举在ac自动机相应节点(状态)的位置从而避免了纯粹的暴力枚举。在匹配的过程中保证不允许非法串被包含进去,设dp[i][j][k]表示处理到第i个字符时,ac自动机中的状态是j,并且包含必有串的状态压缩之后的值为k的最少操作次数和相应的最大的附加值(具体体现在两个三维数组)。那么枚举i-1所有的状态,就能够根据第i个字符在ac自动机中进行转移。
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std; const int N = ;
const int inf = 0x3f3f3f3f;
int n;
int sz;
char str[];
int del[][N][<<]; // 记录某一状态下最少的更改次数
int sco[][N][<<]; // 在满足最少次数的情况下最大的得分,优先更改次数减少,其次是得分的最大化 struct Ac_auto {
int ch[N][];
int fail[N];
int sta[N];
int gain[N];
char kill[N]; // 只取0,1两个值
int idx, root;
int newnd() {
memset(ch[idx], , sizeof (ch[idx]));
gain[idx] = sta[idx] = fail[idx] = kill[idx] = ;
return idx++;
}
void init() {
idx = , root = newnd();
}
void insert(char ss[], int val) {
int len = strlen(ss);
int p = root;
for (int i = ; i < len; ++i) {
char c = ss[i]-'a';
if (!ch[p][c]) ch[p][c] = newnd();
p = ch[p][c];
}
// 由于题目中说明了不包括相同的单词,因此只需要等于赋值
if (val == ) sta[p] = << sz;
else if (val == -) kill[p] = ;
else gain[p] = val;
}
void build() { // 构建失败指针,ac自动机的精华
queue<int>q;
for (int i = ; i < ; ++i) {
if (ch[root][i]) {
q.push(ch[root][i]);
}
}
while (!q.empty()) {
int p = q.front();
q.pop();
for (int i = ; i < ; ++i) {
int v = ch[p][i];
int x = fail[p];
if (v) {
q.push(v);
while (x && !ch[x][i]) x = fail[x]; // 选择一个最长的后缀串,使fail指针指向它
fail[v] = ch[x][i]; // 无论有没有指向i的节点,其fail指针会指向0
kill[v] |= kill[fail[v]]; // 如果该字符串之中含有非法的串,那么非法性质会传递过来
sta[v] |= sta[fail[v]]; // 状态也需要传递
gain[v] += gain[fail[v]]; // 传递值
} else {
ch[p][i] = ch[x][i];
}
}
}
}
}; Ac_auto ac; void solve() {
memset(del, 0x3f, sizeof (del)); // 对于删除次数初始化为正无穷大
memset(sco, 0x80, sizeof (sco)); // 对于得分初始化为负无穷大
int cur = , nxt = ;
del[cur][][] = ; // 初始化没有字符时不包含任何合法和非法的状态的最少更改字符数为0
sco[cur][][] = ; // 配套的获得的价值为0
int len = strlen(str);
int lim = << sz;
const int &idx = ac.idx;
for (int i = ; i < len; ++i) { // i表示匹配到了那个字符
int c = str[i]-'a';
memset(del[nxt], 0x3f, sizeof (del[nxt]));
memset(sco[nxt], 0x80, sizeof (sco[nxt]));
for (int j = ; j < idx; ++j) { // j记录在ac自动机中匹配到的位置
for (int k = ; k < lim; ++k) { // k表示压缩后的包含必须子串的情况
if (del[cur][j][k] == inf) continue; // 如果这个状态没有计算过,其也就无法转移到新的状态
// 如果删除该字符
if (del[nxt][j][k] > del[cur][j][k] + ) {
del[nxt][j][k] = del[cur][j][k] + ;
sco[nxt][j][k] = sco[cur][j][k];
} else if (del[nxt][j][k] == del[cur][j][k] + ) {
if (sco[nxt][j][k] < sco[cur][j][k]) {
sco[nxt][j][k] = sco[cur][j][k];
}
} // 如果匹配该字符
int np = ac.ch[j][c];
if (ac.kill[np]) continue; // 如果不能够匹配或者该子串不允许被包含
int gain = ac.gain[np];
int nsta = k|ac.sta[np];
if (del[nxt][np][nsta] > del[cur][j][k]) {
del[nxt][np][nsta] = del[cur][j][k];
sco[nxt][np][nsta] = sco[cur][j][k] + gain;
} else if (del[nxt][np][nsta] == del[cur][j][k]) {
if (sco[nxt][np][nsta] < sco[cur][j][k] + gain) {
sco[nxt][np][nsta] = sco[cur][j][k] + gain;
}
}
}
}
swap(cur, nxt);
}
int xdel = inf, xsco;
for (int i = ; i < idx; ++i) {
if (xdel > del[cur][i][lim-]) {
xdel = del[cur][i][lim-];
xsco = sco[cur][i][lim-];
} else if (xdel == del[cur][i][lim-]) {
xsco = max(xsco, sco[cur][i][lim-]);
}
}
if (xdel == inf) {
puts("Banned");
} else {
printf("%d %d\n", xdel, xsco);
}
} int main() {
int T, ca = ;
scanf("%d", &T);
while (T--) {
int val;
sz = ;
ac.init();
scanf("%d", &n);
for (int i = ; i < n; ++i) {
scanf("%s %d", str, &val);
ac.insert(str, val);
if (val == ) ++sz;
}
ac.build();
scanf("%s", str);
printf("Case %d: ", ++ca);
solve();
}
return ;
}
HDU-4534 郑厂长系列故事——新闻净化 AC自动机+DP的更多相关文章
- HDU 4539郑厂长系列故事――排兵布阵(状压DP)
HDU 4539 郑厂长系列故事――排兵布阵 基础的状压DP,首先记录先每一行可取的所哟状态(一行里互不冲突的大概160个状态), 直接套了一个4重循环居然没超时我就呵呵了 //#pragma co ...
- HDU 4539 郑厂长系列故事——排兵布阵
http://acm.hdu.edu.cn/showproblem.php?pid=4539 郑厂长系列故事——排兵布阵 Time Limit: 10000/5000 MS (Java/Others) ...
- HDU 4529 郑厂长系列故事——N骑士问题 状压dp
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4529 郑厂长系列故事--N骑士问题 Time Limit: 6000/3000 MS (Java/O ...
- HDU 4539 郑厂长系列故事——排兵布阵 状压dp
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4539 郑厂长系列故事--排兵布阵 Time Limit: 10000/5000 MS (Java/O ...
- HDU 4539 郑厂长系列故事——排兵布阵 —— 状压DP
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4539 郑厂长系列故事——排兵布阵 Time Limit: 10000/5000 MS (Java/Ot ...
- hdu 4524 郑厂长系列故事——逃离迷宫 小水题
郑厂长系列故事——逃离迷宫 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) To ...
- POJ 1185 - 炮兵阵地 & HDU 4539 - 郑厂长系列故事——排兵布阵 - [状压DP]
印象中这道题好像我曾经肝过,但是没肝出来,现在肝出来了也挺开心的 题目链接:http://poj.org/problem?id=1185 Time Limit: 2000MS Memory Limit ...
- HDU 4539 郑厂长系列故事――排兵布阵(曼哈顿距离)
这虽然是中文题,然而没看懂,不懂的地方,就是在曼哈顿距离这块,网上搜索了一下,写了个程序,是测试曼哈顿距离的. 曼哈顿距离:两点(x1,y1)(x2,y2)的曼哈顿距离为|x1-x2|+|y1-y2| ...
- 郑厂长系列故事——体检(hdu 4519)
郑厂长系列故事--体检 Time Limit: 500/200 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total S ...
随机推荐
- ThinkPHP 3.2.3 自动加载公共函数文件的方法
方法一.加载默认的公共函数文件 在 ThinkPHP 3.2.3 中,默认的公共函数文件位于公共模块 ./Application/Common 下,访问所有的模块之前都会首先加载公共模块下面的配置文件 ...
- js判断移动终端url跳转
CODE <script> //判断终端url跳转 function sp_isMobile() { return Boolean(navigator.userAgent.match(/. ...
- JavaScript方法的调用
1.假如是有名字的函数 调用是用名字调用,并且会把返回值赋值给接受它的参数 代码: function f() { alert("我是f"); return '我是返回值'; } f ...
- 【转】发布一个基于NGUI编写的UI框架
发布一个基于NGUI编写的UI框架 1.加载,显示,隐藏,关闭页面,根据标示获得相应界面实例 2.提供界面显示隐藏动画接口 3.单独界面层级,Collider,背景管理 4.根据存储的导航信息完成界面 ...
- SQL ORDER BY 子句
ORDER BY 语句用于对结果集进行排序. ORDER BY 语句 ORDER BY 语句用于根据指定的列对结果集进行排序. ORDER BY 语句默认按照升序对记录进行排序. 如果您希望按照降序对 ...
- 关于IOS的证书、App ID、设备、Provisioning Profile详述
首先,打开developer.apple.com ,在iOS Dev Center打开Certificates, Indentifiers & Profiles认识一下基本结构.列表就包含了开 ...
- 多线程 - CountDownLatch
一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待. 用给定的计数 初始化 CountDownLatch.由于调用了 countDown() 方法,所以在当前计数到达 ...
- webService 发送soap请求,并解析返回的soap报文
本例应用场景:要做一个webService测试功能,不局限于任何一种固定格式的webService,所以像axis,cxf等框架就不好用了.只有深入到webService的原理,通过发收soap报文, ...
- ftp列表错误或长城宽带连不上ftp的解决方法
有些是长城宽带,我 帮忙测试,在客户PC机上测试,PING 任何网站 不通:tracert 超时:FTP 超时,不出现用户名提示.但访问网站正常,检测后进入到路由器,禁用DHCP服务 ,问题解决. 或 ...
- iOS UITableView 移除单元格选中时的高亮状态
在处理UITableView表格时,我们希望用户能够和触摸单元格式进行交互,但是希望用户在完成交互之后,这些单元格的选中状态能够消失,.Cocoa Touch 提供了两种方法来防止单元格背持久选中. ...