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 ...
随机推荐
- Tomcat热部署方法(3种)【转】
热部署是指在你修改项目BUG的时候对JSP或JAVA类进行了修改在不重启WEB服务器前提下能让修改生效.但是对配置文件的修改除外! 1.直接把项目web文件夹放在webapps里. 2.在tomcat ...
- Maven应用
Maven进行项目管理很方便,下面介绍一下学习maven中的笔记.我是在Windows上运行的 有些知识点没有试,只是收集转载,很可能存在错误 1.安装 解压缩之后,配置环境变量MA ...
- angularJS支持的事件
AngularJS提供可与HTML控件相关联的多个事件.例如ng-click通常与按钮相关联.以下是AngularJS支持的事件. ng-click ng-dbl-click ng-mousedown ...
- 史上最臭名昭著五大软件Bug
在现今数字年代,计算机bug不但困扰着每个程序员,更会无可避免影响我们的生活,小到每个人的衣食住行,大到国家经济,世界局势.随着我们的生活方式渐渐的数字化.互联网化,数字世界的找虫和杀虫就变得越来越重 ...
- Scala 流程空间,函数,异常处理
1,)首先留意一下下边的代码块,他是怎么运行的,貌似在c#中他是出错的,不应该出现这样的写法的,但在scala中侧不然: package com.dt.study /** * The package ...
- 自动化环境robot framework安装中问题解决
在搭建自动化环境的时候需要安装以下程序:
- S3C2440 裸机程序之音频
mini2440之Main分析 2012-03-17 20:51:29 分类: 嵌入式 /****************************************************** ...
- STL之容器(1)
STL容器类的模板 容器部分主要由头文件<vector>,<list>,<deque>,<set>,<map>,<stack>和 ...
- CentOS-6 yum安装nginx php53 mysql55 搭建LNMP环境
1.导入外部软件库 01.rpm -Uvh http://dl.iuscommunity.org/pub/ius/stable/Redhat/6/x86_64/epel-release-6-5.noa ...
- 2.在程序中如何实现Cookie信息的设置,读取和删除
设置:你可以在IE的“工具/Internet选项”的“常规”选项卡中,选择“设置/查看文件”,查看所有保存到你电脑里的Cookies.这些文件通常是以user@domain格式命名的,user是你的本 ...