解题思路:

fail树上用权值线段树合并求right/endpos集合,再用倍增找到待查询串对应节点,然后权值线段树求第k大。

#include<bits/stdc++.h>
using namespace std; typedef long long ll;
const int maxn=1e5+5;
int n,q;
char s[maxn]; namespace SegTree{
int sum[maxn*100],L[maxn*100],R[maxn*100];
int tot1;
int update(int rt,int l,int r,int pos,int val){
int nrt=++tot1;
L[nrt]=L[rt]; R[nrt]=R[rt]; sum[nrt]=sum[rt]+val;
if(l!=r){
int mid=(l+r)>>1;
if(pos<=mid)L[nrt]=update(L[rt],l,mid,pos,val);
else R[nrt]=update(R[rt],mid+1,r,pos,val);
}
return nrt;
}
int merge(int rt1,int rt2){
if(!rt1 || !rt2)return rt1|rt2;
int nrt=++tot1;
L[nrt]=L[rt1]; R[nrt]=R[rt1]; sum[nrt]=sum[rt1]+sum[rt2];
L[nrt]=merge(L[rt1],L[rt2]);
R[nrt]=merge(R[rt1],R[rt2]);
return nrt;
} int query(int rt,int l,int r,int k){
if(l==r)return l;
int mid=(l+r)>>1;
if(k<=sum[L[rt]])return query(L[rt],l,mid,k);
return query(R[rt],mid+1,r,k-sum[L[rt]]);
}
}using namespace SegTree; namespace Suffix_Automaton{
int ch[maxn<<1][26],fa[maxn<<1],len[maxn<<1];
int last,tot; int rt[maxn],T[maxn<<1];
int Fa[maxn<<1][20]; inline void init(){
last=tot=1;
len[1]=fa[0]=0;
memset(ch[1],0,sizeof(ch[1])); T[1]=0;
} inline int newnode(){
++tot;
len[tot]=fa[tot]=0;
memset(ch[tot],0,sizeof(ch[tot])); T[tot]=0;
return tot;
} inline void extend(int c,int right){
int p=last,cur=newnode();
len[cur]=len[last]+1;
last=cur; rt[right]=cur;
T[cur]=update(T[cur],1,n,right,1); while(p && !ch[p][c]){
ch[p][c]=cur;
p=fa[p];
}
if(!p)fa[cur]=1;
else{
int q=ch[p][c];
if(len[p]+1==len[q])fa[cur]=q;
else{
int clone=newnode();
len[clone]=len[p]+1;
memcpy(ch[clone],ch[q],sizeof(ch[q]));
fa[clone]=fa[q];
fa[q]=fa[cur]=clone;
while(ch[p][c]==q){
ch[p][c]=clone;
p=fa[p];
}
}
}
} int c[maxn<<1],A[maxn<<1];
inline void init(char *a,int l){
init();
for(int i=1;i<=l;i++)extend(a[i]-'a',i);
for(int i=0;i<=tot;i++)c[i]=0;
for(int i=1;i<=tot;i++)++c[len[i]];
for(int i=1;i<=tot;i++)c[i]+=c[i-1];
for(int i=1;i<=tot;i++)A[--c[len[i]]]=i;
for(int i=tot-1;i>=1;i--)T[fa[A[i]]]=merge(T[fa[A[i]]],T[A[i]]);
for(int i=1;i<=tot;i++)Fa[i][0]=fa[i];
for(int k=1;k<=19;k++)for(int i=1;i<=tot;i++)Fa[i][k]=Fa[Fa[i][k-1]][k-1]; } inline void solve(int l,int r,int k){
int u=rt[r],length=r-l+1;
if(len[fa[u]]+1>length){
for(int k=19;k>=0;k--)if(len[fa[Fa[u][k]]]+1>length)u=Fa[u][k];
u=fa[u];
}
if(k<=sum[T[u]])printf("%d\n",query(T[u],1,n,k)-length+1);
else printf("-1\n");
} }using namespace Suffix_Automaton;
int main()
{
//#ifndef ONLINE_JUDGE
// freopen("in.txt","r",stdin);
//#endif
int T;
scanf("%d",&T);
while(T--){
tot1=0;
scanf("%d %d",&n,&q);
scanf("%s",s+1);
init(s,n);
int l,r,k;
while(q--){
scanf("%d %d %d",&l,&r,&k);
solve(l,r,k);
}
}
return 0;
}

hdu6704 2019CCPC网络选拔赛1003 K-th occurrence 后缀自动机+线段树合并的更多相关文章

  1. hdu6704 2019CCPC网络选拔赛1003 K-th occurrence 后缀数组

    题意:给你一个长度为n的字符串,有q个询问,每次询问一个子串s(l,r)第k次出现的位置,若子串出现次数少于k次输出-1. 解题思路:先把SA跑出来,然后对于每次询问可以由l和rank[]找到l在所有 ...

  2. HDU - 6704 K-th occurrence (后缀数组+主席树/后缀自动机+线段树合并+倍增)

    题意:给你一个长度为n的字符串和m组询问,每组询问给出l,r,k,求s[l,r]的第k次出现的左端点. 解法一: 求出后缀数组,按照排名建主席树,对于每组询问二分或倍增找出主席树上所对应的的左右端点, ...

  3. HDU-6704 K-th occurrence (后缀自动机father树上倍增建权值线段树合并)

    layout: post title: HDU-6704 K-th occurrence (后缀自动机father树上倍增建权值线段树合并) author: "luowentaoaa&quo ...

  4. BZOJ 3065 带插入区间K小值(sag套线段树)

    3065: 带插入区间K小值 Time Limit: 60 Sec  Memory Limit: 512 MBSubmit: 4696  Solved: 1527[Submit][Status][Di ...

  5. [BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树)

    [BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树) 题面 原题面有点歧义,不过从样例可以看出来真正的意思 有n个位置,每个位置可以看做一个集合. ...

  6. SPOJ-COT-Count on a tree(树上路径第K小,可持久化线段树)

    题意: 求树上A,B两点路径上第K小的数 分析: 同样是可持久化线段树,只是这一次我们用它来维护树上的信息. 我们之前已经知道,可持久化线段树实际上是维护的一个前缀和,而前缀和不一定要出现在一个线性表 ...

  7. 树上第k小,可持久化线段树+倍增lca

    给定一颗树,树的每个结点都有权值, 有q个询问,每个询问是 u v k ,表示u到v路径上第k小的权值是多少. 每个结点所表示的线段树,是父亲结点的线段树添加该结点的权值之后形成的新的线段树 c[ro ...

  8. 网络赛 I题 Max answer 单调栈+线段树

    题目链接:https://nanti.jisuanke.com/t/38228 题意:在给出的序列里面找一个区间,使区间最小值乘以区间和得到的值最大,输出这个最大值. 思路:我们枚举每一个数字,假设是 ...

  9. ACM-ICPC 2018 南京赛区网络预赛 G Lpl and Energy-saving Lamps(线段树)

    题目链接:https://nanti.jisuanke.com/t/30996 中文题目: 在喝茶的过程中,公主,除其他外,问为什么这样一个善良可爱的龙在城堡里被监禁Lpl?龙神秘地笑了笑,回答说这是 ...

随机推荐

  1. Reactor 3 参考文档——如何选择操作符

    如果一个操作符是专属于 Flux 或 Mono 的,那么会给它注明前缀.公共的操作符没有前缀.如果一个具体的用例涉及多个操作符的组合,这里以方法调用的方式展现,会以一个点(.)开头,并将参数置于圆括号 ...

  2. 微信号可以改了?我用 Python 发现了隐藏的 6 大秘密.

    “听说,微信可以改微信号了! ” 不知道谁扯了一嗓子,让办公室变成了欢乐的海洋 张姐流下了激动的泪水:“太好了!姐的年龄终于不用暴露在微信号了!” 很多人学习python,不知道从何学起.很多人学习p ...

  3. java_字节流、字符流的使用方法

    字节流 字节输出流[OutputStream] java.io.OutputStream 抽象类是表示字节输出流的所有类的超类,将指定的字节信息写出到目的地.它定义了字节输出流的基本共性功能方法. p ...

  4. git使用-分支管理

    1.查看分支 git branch 2.创建分支 git branch name 3.切换分支 git checkout name 4.合并分支上的内容到master分支 切换到master分支上 g ...

  5. 微信小程序通过二维码获取参数运行

    小程序开发过程中会遇到参数id会通过二维码获取,然后执行接口获取数据,但是难免会遇到带过来的参数出现乱码,这样就需要解码,多个参数时就需要进行处理取我们需要的字段值:小程序开发过程中会遇到参数id会通 ...

  6. Homekit_Dohome_智能插座

    简介: 本款智能插座有三个版本可供选择,分别为Homekit版本,涂鸦版本,Dohome版本,各个版本的区别如下: DoHome版特点: 支持HomeKit 支持Amazon 支持Google ...

  7. Centos系统安装Python3.7

    服务器安装Python3.7,实测可用 原博客地址 首先要先安装依赖包: yum install zlib-devel bzip2-devel openssl-devel ncurses-devel ...

  8. CVE-2020-0796“永恒之黑”漏洞复现

    0x00 漏洞概述 Microsoft Server Message Block 3.1.1(SMBv3)协议在处理某些请求的方式中存在代码执行漏洞.攻击者可以精心构造数据包发送到SMB服务器,无需经 ...

  9. Oracle 多条数据转一行逗号隔开

    wm_concat   例: select wm_concat(市) from pa50 where apa132=省

  10. Docker Run Cadvisor failed: inotify_add_watch /sys/fs/cgroup/cpuacct,cpu: no such file or directory

    原文链接:https://blog.csdn.net/poem_2010/article/details/84836816 没有找这个文件, 这是一个bug,在系统中,是cpu,cpuacct 可以去 ...