HNU 13108-Just Another Knapsack Problem (ac自动机上的dp)
题意:
给你一个母串,多个模式串及其价值,求用模式串拼接成母串(不重叠不遗漏),能获得的最大价值。
分析:
ac自动机中,在字典树上查找时,用dp,dp[i]拼成母串以i为结尾的子串,获得的最大价值,dp[i]=max(dp[i],dp[i-len]+val[tmp])。,len是模式串的长度,val[tmp]为其价值。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <algorithm>
#include<iostream>
using namespace std;
const int maxnode = ;
const int sigma_size = ;
struct Trie{
int dp[];
int ch[maxnode][sigma_size];
int val[maxnode]; //该单词在模式串中出现的次数
int last[maxnode];
int f[maxnode]; //失配数组
int num[maxnode]; //该单词出现在文本串的次数
int pre[maxnode]; //该单词的前驱
int len[maxnode]; //以该单词结尾的单词长度
int Char[maxnode]; //该单词对应的字母
int road[maxnode]; //路径压缩优化 针对计算模式串出现的种数
int sz;
int Newnode()
{
val[sz] = f[sz] = last[sz] = len[sz] = num[sz] = ;
memset(ch[sz], , sizeof ch[sz]);
return sz++;
}
void init(){
sz=;
Newnode();
}
int idx(char c){ return c-'a'; }
void build(char *s,int v){
int u = ;
for(int i = , c; s[i] ;i++){
c = idx(s[i]);
if(!ch[u][c])
ch[u][c] = Newnode();
pre[ch[u][c]] = u;
Char[ch[u][c]] = s[i];
len[ch[u][c]] = len[u]+;
road[ch[u][c]] = ;
u = ch[u][c];
}
val[u] = max(val[u],v);
//num[u] = 0;
//return u;
}
void getFail(){
queue<int> q;
for(int i = ; i<sigma_size; i++)
if(ch[][i]) q.push(ch[][i]);
int r, c, u, v;
while(!q.empty()){
r = q.front(); q.pop();
for(c = ; c<sigma_size; c++){
u = ch[r][c];
if(!u)continue;
q.push(u);
v = f[r];
while(v && ch[v][c] == ) v = f[v]; //沿失配边走上去 如果失配后有节点 且 其子节点c存在则结束循环
f[u] = ch[v][c];
}
}
}
void find(char *T){
//计算模式串出现的个数:(每种多次出现算多次)
int j = ,l=strlen(T);
for(int i = , c, temp; i<l ; i++){
dp[i]=;
c = idx(T[i]);
while(j && ch[j][c]==) j = f[j];
j = ch[j][c]; temp = j;
while(temp){
if(val[temp]){
if(i-len[temp]<)
dp[i]=max(dp[i],val[temp]);
else if(dp[i-len[temp]])
dp[i]=max(dp[i],dp[i-len[temp]]+val[temp]);
}
temp = f[temp];
}
}
printf("%d\n",dp[l-]);
}
int find_kind(char *T){
//计算种数, 重复出现的不再计算(若多个询问则要在此处加for(i=0->sz)lu[i]=1;
int j = , i, c, temp,ans=;
for(i = ; T[i]; i++){
c = idx(T[i]);
while(j && ch[j][c] == ) j = f[j];
j = ch[j][c];
temp = j;
while(temp && road[temp]){
if(val[temp])
{
++ans;
val[temp] = ;
}
road[temp] = ;
temp = f[temp];
}
}
return ans;
}
}ac;
int n,v;
char T[],P[];
int main() {
while(~scanf("%s",T)){
ac.init();
scanf("%d",&n);
while(n--){
scanf("%s%d",P,&v);
ac.build(P,v);
}
ac.getFail();
ac.find(T);
}
}
HNU 13108-Just Another Knapsack Problem (ac自动机上的dp)的更多相关文章
- HNU 13108 Just Another Knapsack Problem DP + Trie树优化
题意: 给你一个文本串,和一些模式串,每个模式串都有一个价值,让你选一些模式串来组成文本串,使获得的价值最大.每个模式串不止能用一次. 思路: 多重背包,枚举文本串的每个位置和模式串,把该模式串拼接在 ...
- POJ 3691 AC自动机上的dp
题目大意: 给定一些不合理的DNA序列,再给一段较长的dna序列,问最少修改几次可以使序列中不存在任何不合理序列,不能找到修改方法输出-1 这里你修改某一个点的DNA可能会影响后面,我们不能单纯的找匹 ...
- BZOJ 1030 文本生成器 | 在AC自动机上跑DP
题目: http://www.lydsy.com/JudgeOnline/problem.php?id=1030 题解: 鸽 #include<cstdio> #include<al ...
- 【BZOJ1030】[JSOI2007] 文本生成器(AC自动机上跑DP)
点此看题面 大致题意: 给你\(N\)个字符串(只含大写字母),要你求出有多少个由\(M\)个大写字母构成的字符串含有这\(N\)个字符串中的至少一个. \(AC\)自动机 看到题目,应该比较容易想到 ...
- hdu 3247 AC自动+状压dp+bfs处理
Resource Archiver Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 100000/100000 K (Java/Ot ...
- URAL 1158 AC自动机上的简单DP+大数
题目大意 在一种语言中的字母表中有N(N<=50)个字母,每个单词都由M(M<=50)个字母构成,因此,一共可以形成N^M个单词.但是有P(P<=10)个串是被禁止的,也就是说,任何 ...
- 【洛谷4045】[JSOI2009] 密码(状压+AC自动机上DP)
点此看题面 大致题意: 给你\(n\)个字符串,问你有多少个长度为\(L\)的字符串,使得这些字符串都是它的子串.若个数不大于\(42\),按字典序输出所有方案. 状压 显然,由于\(n\)很小,我们 ...
- HUNAN 11569 Just Another Knapsack Problem(AC自动机+dp)
http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=11569&courseid=0 给出目标串,每个子串和 ...
- hdu 3992 AC自动机上的高斯消元求期望
Crazy Typewriter Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
随机推荐
- NSString+URLEncoding.h --使用Obj-C对数据等进行URLEncoding编码
在Objective-c进行网络编程时,经常需要把数据转换成URLEncoding编码,如对+号编码后,变成%2b.这里我们给出一种实现. //NSString+URLEncoding.h #impo ...
- java使用正则表达式——实例
Java代码 import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @author Der * ...
- Selenium WebDriver 中鼠标和键盘事件分析及扩展(转)
本文将总结 Selenium WebDriver 中的一些鼠标和键盘事件的使用,以及组合键的使用,并且将介绍 WebDriver 中没有实现的键盘事件(Keys 枚举中没有列举的按键)的扩展.举例说明 ...
- longene QQ 安装目录
longene QQ 在Ubuntu 12.04上的安装目录如下: wy@wy-Inspiron-7420:~/.longene/qq/drive_c/Program Files/Tencent/QQ ...
- 两个List合并,过滤重复记录
import java.util.ArrayList; import java.util.HashSet; import java.util.Hashtable; import java.util.I ...
- 动态调整对话框属性(去掉标题栏,去掉边框,修改类似成Border:NONE样式)(调用ModifyStyle和ModifyStyleEx,然后调用SetWindowPos重新显示)
// 动态修改对话框属性,去掉对话框标题栏,设置Border为NONE属性. if(dlg.GetSafeHwnd()) { dlg.ModifyStyle(WS_CAPTION, 0); // 去掉 ...
- Photoshop:建议设置
一.新建文档设置: 二.对齐设置 菜单->视图->对齐->全部 使用图层.形状等操作时自动对齐网格,画矢量图不怕模糊边缘,确保每个像素保持清晰. 三.首选项设置 关掉"启用 ...
- mysql优化 mysql explain
一篇文章: 使用use index优化sql查询 先看一下arena_match_index的表结构,大家注意表的索引结构CREATE TABLE `arena_match_index` ( ` ...
- Android Studio上的几个插件
转载:http://blog.csdn.net/maosidiaoxian/article/details/44992655 以下所有插件都可以在Idea的插件库中找到,如果你与我一样在Android ...
- C#获取网页中某个元素的位置,并模拟点击
我们在开发中,往往要得到网页中某个元素的位置,并且点击它.要模拟一次鼠标点击并不难,只要调用一个API就行了,关键就是怎么样得到这个元素的位置,还有判断是否要滚动滚动条,要滚动多少行能让元素显示出来. ...