HDU-6704 K-th occurrence (后缀自动机father树上倍增建权值线段树合并)
layout: post
title: HDU-6704 K-th occurrence (后缀自动机father树上倍增建权值线段树合并)
author: "luowentaoaa"
catalog: true
tags:
mathjax: true
- kuangbin
- 字符串
" target="_blank" style="font-size:24px;">传送门
题意
给出一个长度为\(n\)字符串\(s\), \(m\)次询问,每次问你字符串\(s\)区间内的字符串\(l,r\)第\(k\)次出现的位置。
思路
比赛的时候一眼就知道是\(sa\)但是对于\(sa\)实在不喜欢,于是比赛的时候整场用\(sam\)硬怼。已经想到了用主席树记录\(endpos\)位置,然后从后往前推过去,但是比赛时还不会在\(sam\)上玩权值线段树合并,赛后学习了一下。
首先,这题我们可以在\(sam\)上的每个新开节点上存储这个节点是在原串的那个位置是把。
然后对于一个串\(i\)他的\(father\)肯定是他的\(后缀\) 所以他的\(endpos\)肯定也是他\(father\)的\(endpos\)
同时一个\(father\)不仅仅只有\(i\)这个儿子 所以\(father\)的继承是从很多儿子那边的来的,于是我们需要搞笑处理继承效果,这里用到了权值线段树合并,线段树下标是\(endpos\)在\(s\)的位置。
这样我们就可以通过找到一个点而得出这个点所有的\(endpos\) ,也可以很快的在权值线段树中找到第\(k\)大的$endpos \(。但是\)Q$次查询每次都可能用一个长度\(1e5\)的串进入\(sam\)中找这个点的位置,于是我们考虑离线操作,将询问按照\(r\)排序。但是我们找到了一个点之后可能这个长度太大了,于是我们需要跳到这个点的\(father\) 知道这个点的长度刚好大于等于我们需要的长度,这样答案才完整。因为\(father\)的长度是单调的,于是我们可以考虑用树上倍增 快速找到合适的\(father\)。
于是这题就愉快的结束了。真爽啊。debug都不需要。
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int maxn=5e5+50;
int ls[maxn*80],rs[maxn*80],rt[maxn*80],sum[maxn*80],cnt;
void update(int &o,int l,int r,int pos){
if(!o)o=++cnt;
if(l==r){
sum[o]++;return;
}
int mid=(l+r)/2;
if(pos<=mid)update(ls[o],l,mid,pos);
else update(rs[o],mid+1,r,pos);
sum[o]=sum[ls[o]]+sum[rs[o]];
}
int merger(int o,int pre,int l,int r){
if(!o)return pre;if(!pre)return o;
int k=++cnt;
if(l==r){
sum[k]=sum[o]+sum[pre];
return k;
}int mid=(l+r)/2;
ls[k]=merger(ls[o],ls[pre],l,mid);
rs[k]=merger(rs[o],rs[pre],mid+1,r);
sum[k]=sum[ls[k]]+sum[rs[k]];
return k;
}
int query(int o,int l,int r,int k){
if(sum[o]<k)return -1;
if(l==r)return l;
int mid=(l+r)/2;
if(sum[ls[o]]>=k)return query(ls[o],l,mid,k);
else return query(rs[o],mid+1,r,k-sum[ls[o]]);
}
struct Q{
int l,r,k,id;
bool operator<(const Q &o)const{
return r<o.r;
}
}my[maxn];
int n;
char s[maxn];
int ans[maxn];
struct SAM{
int fa[maxn],ch[maxn][26],maxlen[maxn],tot,last;
int sz[maxn],a[maxn],b[maxn];
void init(){
cnt=0;
fill(rt,rt+n*80,0);
fill(ls,ls+n*80,0);
fill(rs,rs+n*80,0);
fill(sum,sum+n*80,0);
tot=last=1;maxlen[1]=fa[1]=0;
memset(ch[1],0,sizeof(ch[1]));
}
void add(int x,int id){
int np=++tot,p=last;last=np;update(rt[np],1,n,id);
maxlen[np]=maxlen[p]+1;sz[np]=1;
memset(ch[np],0,sizeof(ch[np]));
while(p&&!ch[p][x])ch[p][x]=np,p=fa[p];
if(!p)fa[np]=1;
else{
int q=ch[p][x];
if(maxlen[q]==maxlen[p]+1)fa[np]=q;
else{
int nq=++tot;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
fa[nq]=fa[q],fa[np]=fa[q]=nq;
maxlen[nq]=maxlen[p]+1;
while(p&&ch[p][x]==q)ch[p][x]=nq,p=fa[p];
}
}
}
int pa[maxn][25];
void Sort(){///拓扑排序 得到每个集合里的串出现次数
for(int i=1;i<=tot;i++)a[i]=0;
for(int i=1;i<=tot;i++)a[maxlen[i]]++;
for(int i=1;i<=tot;i++)a[i]+=a[i-1];
for(int i=1;i<=tot;i++)b[a[maxlen[i]]--]=i;
for(int i=tot;i;i--)sz[fa[b[i]]]+=sz[b[i]];
for(int i=tot;i;i--){
int k=b[i];
pa[k][0]=fa[k];
rt[fa[k]]=merger(rt[fa[k]],rt[k],1,n);
}
for(int i=1;i<=20;i++){
for(int j=1;j<=tot;j++){
int v=pa[j][i-1];
pa[j][i]=pa[v][i-1];
}
}
}
int go(int id,int len){
for(int i=20;i>=0;i--){
if(maxlen[pa[id][i]]>=len)id=pa[id][i];
}
return id;
}
int m;
void slove(){
for(int i=1;i<=m;i++){
cin>>my[i].l>>my[i].r>>my[i].k;
my[i].id=i;
}
sort(my+1,my+1+m);
int now=1;
int tail=1;
for(int i=1;i<=n;i++){
int x=s[i]-'a';
now=ch[now][x];
while(tail<=m&&my[tail].r==i){
int len=my[tail].r-my[tail].l+1;
int where=go(now,len);
int aa=query(rt[where],1,n,my[tail].k);
if(aa==-1)ans[my[tail].id]=-1;
else{
ans[my[tail].id]=aa-len+1;
}
tail++;
}
}
for(int i=1;i<=m;i++)cout<<ans[i]<<endl;
}
}S;
int main()
{
std::ios::sync_with_stdio(false);
int t;
cin>>t;
while(t--){
cin>>n;cin>>S.m;
cin>>s+1;
n=strlen(s+1);S.init();
for(int i=1;i<=n;i++)S.add(s[i]-'a',i);
S.Sort();
S.slove();
}
return 0;
}
HDU-6704 K-th occurrence (后缀自动机father树上倍增建权值线段树合并)的更多相关文章
- 区间第k大问题 权值线段树 hdu 5249
先说下权值线段树的概念吧 权值平均树 就是指区间维护值为这个区间内点出现次数和的线段树 用这个加权线段树 解决第k大问题就很方便了 int query(int l,int r,int rt,int k ...
- HDU 6464 免费送气球 【权值线段树】(广东工业大学第十四届程序设计竞赛)
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6464 免费送气球 Time Limit: 2000/1000 MS (Java/Others) M ...
- 2019年CCPC网络赛 HDU 6703 array【权值线段树】
题目大意:给出一个n个元素的数组A,A中所有元素都是不重复的[1,n].有两种操作:1.将pos位置的元素+1e72.查询不属于[1,r]中的最小的>=k的值.强制在线. 题解因为数组中的值唯一 ...
- R - Weak Pair HDU - 5877 离散化+权值线段树+dfs序 区间种类数
R - Weak Pair HDU - 5877 离散化+权值线段树 这个题目的初步想法,首先用dfs序建一颗树,然后判断对于每一个节点进行遍历,判断他的子节点和他相乘是不是小于等于k, 这么暴力的算 ...
- BZOJ 3110 ZJOI 2013 K大数查询 树套树(权值线段树套区间线段树)
题目大意:有一些位置.这些位置上能够放若干个数字. 如今有两种操作. 1.在区间l到r上加入一个数字x 2.求出l到r上的第k大的数字是什么 思路:这样的题一看就是树套树,关键是怎么套,怎么写.(话说 ...
- 动态求区间K大值(权值线段树)
我们知道我们可以通过主席树来维护静态区间第K大值.我们又知道主席树满足可加性,所以我们可以用树状数组来维护主席树,树状数组的每一个节点都可以开一颗主席树,然后一起做. 我们注意到树状数组的每一棵树都和 ...
- HDU - 2665 Kth number 主席树/可持久化权值线段树
题意 给一个数列,一些询问,问$[l,r]$中第$K$大的元素是哪一个 题解: 写法很多,主席树是最常用的一种之一 除此之外有:划分树,莫队分块,平衡树等 主席树的定义其实挺模糊, 一般认为就是可持久 ...
- BZOJ3110[Zjoi2013]K大数查询——权值线段树套线段树
题目描述 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是 ...
- HDU - 5592 ZYB's Premutation (权值线段树)
题意:给出序列前k项中的逆序对数,构造出这个序列. 分析:使用权值线段树来确定序列元素. 逆序对的数量肯定是递增的,从最后一个元素开始逆向统计,则\(a[i] - a[i-1]\)即位置i之前比位置i ...
随机推荐
- The Road to SDN: An Intellectual History of Programmable Networks
文章名称:The Road to SDN: An Intellectual History of Programmable Networks 文章来源:Feamster N , Rexford J , ...
- nodejs的npm命令无反应的解决方案
这二天用npm下载模块的时候输入npm命令完全无反应,不是加载的那种状态而是下标不停地在哪里闪...之后找解决方案,说要删除npmrc文件.强调:不是nodejs安装目录npm模块下的那个npmrc文 ...
- ZR#710
雷劈数 题意: 现在给出两个整数,求出位于两个整数之间的所有的"雷劈数. 解法: 因为雷劈数特殊的性质,所以在数据范围中的雷劈数实际很少,直接暴力打表就行. CODE: #include&l ...
- maven在pom文件中引入了icepdf-core包,pom文件却莫名的报错,说jai_core包missing
maven在pom文件中引入了icepdf-core包,却莫名的报错,说jai_core包missing,把这个jai_core包引入之后还是一样报错,PS:icepdf-core使用的时候不用引用j ...
- Netfilter 之 table、rule、match、target
概述 本文主要分析table,rule,match,target的作用和其数据结构之间的关系,为后面的匹配流程做铺垫,通过本文中代码流程的分析,可以得到如下的关系图: 详细分析 table iptab ...
- react 闲谈
从事前端一段时间了,公司用的框架都是vue,但是不知为何对react却情有独钟,这是不是所谓的吃着碗里的看着锅里的 哈哈哈 从头好好总结下react吧 小白一个 大神勿喷 瞎说一 react是由两部分 ...
- <HTML>在一个表格内嵌套另一个表格时,如何居中?
在一个表格内嵌套另一个表格时,如何居中? 假设大表格为: <table id="tableRow"> <tr> <th>City</th& ...
- Android蓝牙开发技术学习总结
Android开发,提供对蓝牙的通讯栈的支持,允许设别和其他的设备进行无线传输数据.应用程序层通过安卓API来调用蓝牙的相关功能,这些API使程序无线连接到蓝牙设备,并拥有P2P或者多端无线连接的特性 ...
- CentOS 7系统配置上的变化
http://www.linuxidc.com/Linux/2014-09/107375p4.htm CentOS 7系统配置上的变化解析 ip ss指令替代 ifconfig route arp n ...
- [Spark] Scala programming - basic level
环境配置 IDE: https://www.jetbrains.com/idea/ 子雨大数据之Spark入门教程(Scala版) /* implement */ 语言特性 Online compil ...