HDU 4117 GRE Words
这道题不难想到这样的dp。
dp[字符串si] = 以si为结尾的最大总权值。
dp[si] = max(dp[sj]) ,1.j < i,2.sj是si的子串。
对于第二个条件,是一个多模版串匹配的问题,可以用AC自动机。
预先O(m)把AC自动机建好,然后动态更新AC自动机上的dp值,
匹配的时候,指向字符的指针移动总共是O(m),
而每个单词,fail指针走寻找后缀却是O(m),即使改成后缀链接也是O(n)。too slow!
找到一个单词后,需要避免找后缀,动态维护这个单词的dp值。
一开始所有单词的dp都是0。
更新的时候,dp[si]需要更新所有dp[sj],其中si是sj的后缀。
如果父节点是子节点的后缀,把所有的单词(包括空后缀)连接起来将会得到以空字符串为根的后缀链接树。
这样就变成一个更新子树的问题,dfs把树形转成线性以后可以用线段树来维护。
询问单点最大值,区间更新O(logn)。
复杂度O(mlogn)
潜在的坑点:
1.Trie个结点可能对应多个单词,如果只更新了其中一个单词的线性区间RE...(map,前向链表,vector都可以搞
/*********************************************************
* ------------------ *
* author AbyssFish *
**********************************************************/
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std; const int LEN = 3e5+;
const int MAXN = 2e4+; int W[MAXN], S[MAXN];
int N;
char s[LEN]; int hd[LEN];
int nx[MAXN], to[MAXN], ec; void add_e(int u,int v)
{
to[ec] = v;
nx[ec] = hd[u];
hd[u] = ec++;
}
#define eachedge int i = hd[u]; ~i; i = nx[i]
inline void init_g(int n){ memset(hd,-,n<<); ec = ; }
int L[MAXN], R[MAXN], dfs_clk; //string's linear suffix link tree id
const int ST_SIZE = <<;
int dp[ST_SIZE]; #define para int o = 1,int l = 0,int r = dfs_clk
#define lo (o<<1)
#define ro (o<<1|1)
#define Tvar int md = (l+r)>>1;
#define lsn lo,l,md
#define rsn ro,md,r
#define insd ql<=l&&r<=qr void build(para)
{
dp[o] = ;
if(r-l>){
Tvar
build(lsn);
build(rsn);
}
} void update(int ql,int qr,int v,para)
{
if(insd){
dp[o] = max(dp[o],v);
}
else {
Tvar
if(ql < md) update(ql,qr,v,lsn);
if(qr > md) update(ql,qr,v,rsn);
}
} int query(int p,para)
{
int re = ;
while(r-l>){
Tvar
if(p<md){
o = lo; r = md;
}
else {
o = ro; l = md;
}
re = max(re,dp[o]);
}
return re;
} const int sigma_size = , MAXND = LEN;
struct AhoCorasick_automata
{
#define idx(x) (x-'a')
int ch[MAXND][sigma_size]; int f[MAXND];
int last[MAXND];
int cnt; int val[MAXND];
int nx_val[MAXN];
void add_v(int o,int x)
{
nx_val[x] = val[o];
val[o] = x;
} int newNode()
{
int i = ++cnt;
memset(ch[i],,sizeof(ch[i]));
val[i] = ;
return i;
} void init()
{
cnt = -; newNode();
} int add(char *s,int id)
{
int u = , i, c;
for(i = ; s[i]; i++){
c = idx(s[i]);
if(!ch[u][c]){
ch[u][c] = newNode();
}
u = ch[u][c];
}
add_v(u,id);
return i;
} queue<int> q;
void getFail()
{
int u, c, v, r;
//f[0] = 0; last[0] = 0;
for(c = ; c < sigma_size; c++){
u = ch[][c];
if(u){
q.push(u);
f[u] = ;
last[u] = ;
}
}
while(!q.empty()){
r = q.front(); q.pop();
for(c = ; c < sigma_size; c++){
u = ch[r][c];
if(u){
q.push(u);
v = f[u] = ch[f[r]][c];
last[u] = val[v] ? v : last[v];
}
else ch[r][c] = ch[f[r]][c];
}
}
} void dfs(int u)
{
int le = dfs_clk++;
for(eachedge){
dfs(to[i]);
}
int ri = dfs_clk;
for(int id = val[u]; id; id = nx_val[id]){
L[id] = le; R[id] = ri;
}
} void buildTree()
{
init_g(cnt+);
for(int u = ; u <= cnt; u++)if(val[u]){
add_e(last[u],u);
}
dfs_clk = ;
dfs();
} void work()
{
int i,j,c,u,id;
int ans = , mx;
build();
for(i = ; i <= N; i++){
u = ; mx = ;
for(j = S[i-]; j < S[i]; j++){
c = idx(s[j]);
u = ch[u][c];
if(val[u]){
id = val[u];
mx = max(mx, query(L[id]));
}
else if(last[u]){
id = val[last[u]];
mx = max(mx, query(L[id]));
}
}
if(W[i] > ){
ans = max(ans, mx += W[i]);
update(L[i],R[i],mx);
}
}
printf("%d\n",ans);
} }ac; void solve()
{
scanf("%d",&N);
ac.init();
for(int i = ; i <= N; i++){
scanf("%s%d",s+S[i-],W+i);
S[i] = ac.add(s+S[i-],i)+S[i-];
}
ac.getFail();
ac.buildTree();
ac.work();
} //#define LOCAL
int main()
{
#ifdef LOCAL
freopen("data.txt","r",stdin);
#endif
int T, kas = ; scanf("%d",&T);
while(++kas <= T){
printf("Case #%d: ",kas);
solve();
}
return ;
}
HDU 4117 GRE Words的更多相关文章
- hdu 4117 -- GRE Words (AC自动机+线段树)
题目链接 problem Recently George is preparing for the Graduate Record Examinations (GRE for short). Obvi ...
- hdu 4117 GRE Words AC自动机DP
题目:给出n个串,问最多能够选出多少个串,使得前面串是后面串的子串(按照输入顺序) 分析: 其实这题是这题SPOJ 7758. Growing Strings AC自动机DP的进阶版本,主题思想差不多 ...
- hdu 4117 GRE Words (ac自动机 线段树 dp)
参考:http://blog.csdn.net/no__stop/article/details/12287843 此题利用了ac自动机fail树的性质,fail指针建立为树,表示父节点是孩子节点的后 ...
- [HDU 4787] GRE Words Revenge (AC自动机)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4787 题目大意: 给你若干个单词,查询一篇文章里出现的单词数.. 就是被我水过去的...暴力重建AC自 ...
- 综合(奇技淫巧):HDU 5118 GRE Words Once More!
GRE Words Once More! Time Limit: 5000/5000 MS (Java/Others) Memory Limit: 512000/512000 K (Java/O ...
- ●HDU 4787 GRE Words Revenge
题链: http://acm.hdu.edu.cn/showproblem.php?pid=4787 题解: AC自动机(强制在线构造) 题目大意: 有两种操作, 一种为:+S,表示增加模式串S, 另 ...
- HDU 5118 GRE Words Once More!
题目链接:HDU-5118 题意:给定一个有向无环图,每条边有一个权值.标定一些特定节点为“特殊节点”.从节点1出发到某“特殊节点”结束的路径,称为一个“GRE单词”.单词由路径上的权值组成.给定一组 ...
- HDU 4787 GRE Words Revenge
Description Now Coach Pang is preparing for the Graduate Record Examinations as George did in 2011. ...
- [GodLove]Wine93 Tarining Round #4
比赛链接: http://acm.hust.edu.cn/vjudge/contest/view.action?cid=44903#overview 题目来源: 2011 Asia ChengDu R ...
随机推荐
- 字符型图片验证码,使用tensorflow实现卷积神经网络,进行验证码识别CNN
本项目使用卷积神经网络识别字符型图片验证码,其基于 TensorFlow 框架.它封装了非常通用的校验.训练.验证.识别和调用 API,极大地减低了识别字符型验证码花费的时间和精力. 项目地址: ht ...
- day07 - Python - 面向对象进阶
本节内容: 面向对象高级语法部分异常处理异常处理异常处理 经典类vs新式类 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 作业:开发一个支持多用户在线的FTP程序 面向对象高级语法部分 1 ...
- Unable to connect to data source (DSN: shangjihuiclient; Network Address: ; Port Number: 53397). Cannot connect to TimesTen Server. Verify that the TimesTen Server is running or verify that your TCP PORT is set correctly.
安装完毕TimesTen后,在客户端连接时一直报错. 解决办法是:重启服务器,在连接没在报这个错误.
- java语言编程使用正则表达式来实现提取(美团 3-5年经验 15-30k 北京 hadoop高级工程)中的3-5和15-30
不多说,直接上干货! 如有这样的一条数据进来: 美团 3-5年经验 15-30k 北京 hadoop高级工程 //正则表达式提取工资值,因为15-30k后面有k,3-5年经验,不干净 public ...
- zookeeper JAVA API 简单操作
package org.admln.program.Zoo_Test; import java.io.IOException; import java.security.NoSuchAlgorithm ...
- 关于GitHub在VS中出现“已经存在master版本,无法……”的错误解决方案
引用:http://www.cnblogs.com/SmallZL/p/3637613.html(这篇已经很详细说明如何使用Vs+GitHub),我这里做补充: VS2013已经集成了Git一部分控件 ...
- 1.3 js基础
1.操作样式 .style 操作行间样式 .className 直接修改class 2.操作属性 . 操作已有的属性 [] 点能做的方括号都能做,方括号里放字符串,能放变量. 3. ...
- java io 学习笔记(一)
java的IO操作都在java.io包下面,这个包下面有12个接口和而是多各类,类从读写的角度可以分为两种,一种是用于读,一种是用于写:从字符流字节流的角度,也可以分为两种,一种和字符有关,一种和字节 ...
- jquery点击事件后增加克隆的标签,并改变克隆的属性加入
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Linux VFS机制简析(一)
Linux VFS机制简析(一) 本文主要基于Linux内核文档,简单分析Linux VFS机制,以期对编写新的内核文件系统(通常是给分布式文件系统编写内核客户端)的场景有所帮助. 个人渊源 切入正文 ...