【题解】GRE Words(UVA1502)
稍微有点难度……不过没有孔姥爷毒瘤(
题意
给定一个单词表,每个单词有权值,取出一部分(不改变顺序)使得这部分的每一个字符串都是后一个的子串,问得到的最大权值。
思路
设 f[i] 表示选了第 i 个字符串之后得到的最大值(截止)\(f[i]=max(f[j])+w[i]\), iff s[j]是s[i]的子串且j<i;
反向建 fail 树,那么对于串 s[i] 的最后一位指向的孩子,均是包含s[i]的串,所以 s[i] 最后一位的子树中孩子节点均包含 s[i]
那么对串 s[1]~s[n] 进行计算时,可以把结果用线段树更新到子树,计算时只需考虑s[i]的每一位能得到的最大值(单点查询),
最后取 max+w[i] 为 s[i] 最大值,更新即可。
代码
#include <bits/stdc++.h>
using namespace std;
const int N=2e4+10,M=3e5+10;
struct edge
{
int nxt,to;
}e[M];
char s[M];
int w[N],pos[N],tr[M][26],fail[M],rt,tot,head[M],cnt,n;
int in[M],out[M],tp,tx[M<<2],tf[M<<4],L,R,tmp;
int newnode()
{
tot++; memset( tr[tot],0,sizeof(tr[tot]) );
fail[tot]=0; return tot;
}
void add( int u,int v )
{
e[cnt].to=v; e[cnt].nxt=head[u]; head[u]=cnt++;
}
void insert( char *s )
{
int p=rt;
for ( int i=0; s[i]; i++ )
{
int ch=s[i]-'a';
if ( !tr[p][ch] ) tr[p][ch]=newnode();
p=tr[p][ch];
}
}
void build()
{
queue<int> q; q.push(rt);
while ( !q.empty() )
{
int now=q.front(); q.pop();
if ( now!=rt ) add( fail[now],now );
for ( int i=0; i<26; i++ )
if ( tr[now][i] )
{
if ( now!=rt ) fail[tr[now][i]]=tr[fail[now]][i];
q.push( tr[now][i] );
}
else tr[now][i]=tr[fail[now]][i];
}
}
void dfs( int now )
{
in[now]=++tp;
for ( int i=head[now]; i; i=e[i].nxt )
dfs( e[i].to );
out[now]=tp;
}
void pushdown( int i )
{
if ( !tf[i] ) return;
int pre=tf[i];
tf[i<<1]=max( tf[i<<1],pre ); tf[i<<1|1]=max( tf[i<<1|1],pre );
tx[i<<1]=max( tx[i<<1],pre ); tx[i<<1|1]=max( tx[i<<1|1],pre );
tf[i]=0;
}
int query( int l,int r,int p )
{
if ( l==r ) return tx[p];
int mid=(l+r)>>1;
pushdown(p);
if ( L<=mid ) return query( l,mid,p<<1 );
else return query( mid+1,r,p<<1|1 );
}
void update( int l,int r,int p )
{
if ( L<=l && r<=R )
{
tf[p]=max( tf[p],tmp ); tx[p]=max( tx[p],tmp ); return;
}
int mid=(l+r)>>1; pushdown(p);
if ( L<=mid ) update( l,mid,p<<1 );
if ( R>mid ) update( mid+1,r,p<<1|1 );
tx[p]=max( tx[p<<1],tx[p<<1|1] );
}
void init()
{
tot=-1; cnt=1; tp=0; rt=newnode();
memset( head,0,sizeof(head) ); memset( fail,0,sizeof(fail) );
memset( tx,0,sizeof(tx) ); memset( tf,0,sizeof(tf) );
}
int main()
{
int T; scanf( "%d",&T );
for ( int cas=1; cas<=T; cas++ )
{
init(); scanf( "%d",&n );
for ( int i=1; i<=n; i++ )
{
scanf( "%s%d",s+pos[i-1],w+i );
pos[i]=pos[i-1]+strlen(s+pos[i-1]); insert( s+pos[i-1] );
}
build(); dfs( rt ); int ans=0;
for ( int i=1; i<=n; i++ )
{
tmp=0; int now=rt;
for ( int j=pos[i-1]; j<pos[i]; j++ )
{
now=tr[now][s[j]-'a']; L=R=in[now];
int res=query( 1,tp,1 ); tmp=max( tmp,res );
}
tmp+=w[i]; ans=max( ans,tmp );
L=in[now]; R=out[now]; update( 1,tp,1 );
}
printf( "Case #%d: %d\n",cas,ans );
}
}
【题解】GRE Words(UVA1502)的更多相关文章
- 题解 GRE Words Revenge
题目传送门 题目大意 给出 \(m\) 次操作,分别为以下两种操作: 学习一个单词 给出一个段落,查询里面有多少个学过的单词.注意,如果学习过 \(\text{ab,bc}\) ,当前查询段落为 \( ...
- 2014ACM/ICPC亚洲区北京站题解
本题解不包括个人觉得太水的题(J题本人偷懒没做). 个人觉得这场其实HDU-5116要比HDU-5118难,不过赛场情况似乎不是这样.怀疑是因为老司机带错了路. 这套题,个人感觉动态规划和数论是两个主 ...
- HDU 5118 GRE Words Once More!
题目链接:HDU-5118 题意:给定一个有向无环图,每条边有一个权值.标定一些特定节点为“特殊节点”.从节点1出发到某“特殊节点”结束的路径,称为一个“GRE单词”.单词由路径上的权值组成.给定一组 ...
- HDU4117 GRE WORDS(AC自动机+线段树维护fail树的dfs序)
Recently George is preparing for the Graduate Record Examinations (GRE for short). Obviously the mos ...
- 【题解】GREWords(AC自动机)
[题解]GREWords(AC自动机) SP9941 GRE - GRE Words 题目大意: 给定一个由字符串构成的序列,不同位置的字符串有自己权值.现在让你选出一个子序列,使得在这个子序列中,前 ...
- HDU4787 GRE Words Revenge【AC自动机 分块】
HDU4787 GRE Words Revenge 题意: \(N\)次操作,每次记录一个\(01\)串或者查询一个\(01\)串能匹配多少个记录的串,强制在线 题解: 在线的AC自动机,利用分块来降 ...
- 2016 华南师大ACM校赛 SCNUCPC 非官方题解
我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...
- noip2016十连测题解
以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...
- BZOJ-2561-最小生成树 题解(最小割)
2561: 最小生成树(题解) Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1628 Solved: 786 传送门:http://www.lyd ...
随机推荐
- shell编程之awk
awk是一种用于处理数据和生成报告的编程语言 awk可以在命令行中进行一些简单的操作,也可以被写成脚本来处理较大的应用问题 awk与grep.sed结合使用,将使shell编程更加容易 awk工作模式 ...
- 创建Grafana监控视图
前言 Grafana允许查询,可视化,警报和了解指标,无论它们存储在哪里. 可视化:具有多种选项的快速灵活的客户端图.面板插件提供了许多不同的方式来可视化指标和日志. 动态仪表盘:使用模板变量创建动态 ...
- SSY的队列 hash+记忆化
题目描述 \(SSY\) 是班集体育委员,总喜欢把班级同学排成各种奇怪的队形,现在班级里有 \(N\) 个身高互不相同的同学,请你求出这 \(N\) 个人的所有排列中任意两个相邻同学的身高差均不为给定 ...
- JAVA学习准备
Java学习准备 MarkDown语法学习 字体 hello,world! hello,world! hello,world! 引用 即使最小的帆也能远航 分割线 图片 超链接 点击跳转到我的邮箱 列 ...
- centos7单独编译nbd内核模块
前言 centos7默认内核没有带nbd的模块,可以通过下载跟当前版本匹配的内核源码,编译源码指定的模块,然后加载到系统 步骤 判断版本 [root@lab201 linux-3.10.0-957.e ...
- Python生成csv中文乱码解决办法
前言 在Linux下面用python进行数据处理,然后输出为csv格式,如果没有中文一切正常,但是如果有中文,就会出现乱码的问题,本篇将讲述怎么处理这个问题 处理过程 原始代码 #!/usr/bin/ ...
- SQL Server 批量生成数据库内多个表的表结构
在遇到大型数据库的时候,一个数据库内存在大量的数据表,如果要生成多个表的表结构,一个表的检索,然后右键Create出来,太麻烦了. 下面我介绍下批量选择并生成多个表的表结构快捷方式,仅供参考. 第一步 ...
- List、Tuple、Set、Dictionary数据类型
一.List数据类型 1.概述:list(列表)中可以包含多个元素,且元素类型可以不相同. 每一元素可以是任意数据类型,包括列表(即列表嵌套)及后面要介绍的元组.集合.字典. 所有元素都写在一对方括号 ...
- oss文件上传删除(批量删除)处理
博主用的是阿里云的oss 首先先在阿里云下载安装sdk,相关的sdk下载请自行到阿里云下载 文档地址 https://help.aliyun.com/document_detail/85580.h ...
- ABBYY FineReader 与尚书七号OCR的对比
ABBYY FineReader 与尚书七号OCR都是帮助我们识别文字的工具,使用的都是OCR技术,如今文字识别工具是我们学习和工作经常会使用的,它们的功能是否实用和好用?现在通过对比的方式来探讨. ...