【题解】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 ...
随机推荐
- 基于Docker UI 配置ceph集群
前言 前一篇介绍了docker在命令行下面进行的ceph部署,本篇用docker的UI进行ceph的部署,目前来说市面上还没有一款能够比较简单就能直接在OS上面去部署Ceph的管理平台,这是因为OS的 ...
- 新手避坑 -- 用 Jenkins +miniprogram-ci 自动构建微信小程序
先看看效果: 要实现这样的效果,需要下面3步: 1.下载 node 依赖包 miniprogram-ci,编写预览和上传功能 2. 登录微信公众平台, 下载项目的privateKey+添加代码上传IP ...
- linx mysql安装
文章引用:https://www.cnblogs.com/shizhongyang/p/8464876.html 只做了少量修改,感谢博主 注:未防止混淆,这里都用绝对路径执行命令 除了文件内容中的# ...
- 测试_QTP使用实例
1. QTP简介 1.1QTP功能与特点 QTP是QuickTest Professional的简称,是一种自动化软件测试工具.在软件的测试过程中,QTP主要来用来通过已有的测试脚本执行重复的手动测试 ...
- javascript九宫格碰撞检测
JS九宫格碰撞检测这个东西 以前学过 这次主要是做面试项目web版的win10 桌面图片需要用碰撞检测 再写的时候竟然完全忘记了碰撞检测原理 和怎么写 综合来说还是写的太少 今天再学了一下 理 ...
- 重闯Sqli-labs关卡第三天(6-10关)
第六关(双注入GET双引号字符型注) 核心代码: 1 $id = '"'.$id.'"'; 2 $sql="SELECT * FROM users WHERE id=$i ...
- Springboot 框架整理,建议做开发的都看看,整理的比较详细!
什么是 Spring Boot? SpringBoot是Spring项目中的一个子工程,与我们所熟知的Spring-framework 同属于spring的产品,是用来简化 spring 初始搭建和开 ...
- Hadoop优化之数据压缩
bBHadoop数据压缩 概述 运行hadoop程序时,I/O操作.网络数据传输.shuffle和merge要花大量的时间,尤其是数据规模很大和工作负载密集的情况下,这个时候,使用数据压缩可以提高效率 ...
- Problem D. Country Meow 题解(三分套三分套三分)
题目链接 题目大意 给你n(n<=100)个点,要你找一个点使得和所有点距离的最大值最小值ans 题目思路 一直在想二分答案,但是不会check 这个时候就要换一下思想 三分套三分套三分坐标即可 ...
- 方格取数(number) 题解(dp)
题目链接 题目大意 给你n*m个方格,每个格子有对应的值 你从(1,1)出发到(n,m)每次只能往下往上往右,走过的点则不能走 求一条路线使得走过的路径的权值和最大 题目思路 如果只是简单的往下和往右 ...