hdu6704 2019CCPC网络选拔赛1003 K-th occurrence 后缀自动机+线段树合并
解题思路:
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 后缀自动机+线段树合并的更多相关文章
- hdu6704 2019CCPC网络选拔赛1003 K-th occurrence 后缀数组
		题意:给你一个长度为n的字符串,有q个询问,每次询问一个子串s(l,r)第k次出现的位置,若子串出现次数少于k次输出-1. 解题思路:先把SA跑出来,然后对于每次询问可以由l和rank[]找到l在所有 ... 
- HDU - 6704 K-th occurrence (后缀数组+主席树/后缀自动机+线段树合并+倍增)
		题意:给你一个长度为n的字符串和m组询问,每组询问给出l,r,k,求s[l,r]的第k次出现的左端点. 解法一: 求出后缀数组,按照排名建主席树,对于每组询问二分或倍增找出主席树上所对应的的左右端点, ... 
- HDU-6704 K-th occurrence (后缀自动机father树上倍增建权值线段树合并)
		layout: post title: HDU-6704 K-th occurrence (后缀自动机father树上倍增建权值线段树合并) author: "luowentaoaa&quo ... 
- BZOJ 3065 带插入区间K小值(sag套线段树)
		3065: 带插入区间K小值 Time Limit: 60 Sec Memory Limit: 512 MBSubmit: 4696 Solved: 1527[Submit][Status][Di ... 
- [BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树)
		[BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树) 题面 原题面有点歧义,不过从样例可以看出来真正的意思 有n个位置,每个位置可以看做一个集合. ... 
- SPOJ-COT-Count on a tree(树上路径第K小,可持久化线段树)
		题意: 求树上A,B两点路径上第K小的数 分析: 同样是可持久化线段树,只是这一次我们用它来维护树上的信息. 我们之前已经知道,可持久化线段树实际上是维护的一个前缀和,而前缀和不一定要出现在一个线性表 ... 
- 树上第k小,可持久化线段树+倍增lca
		给定一颗树,树的每个结点都有权值, 有q个询问,每个询问是 u v k ,表示u到v路径上第k小的权值是多少. 每个结点所表示的线段树,是父亲结点的线段树添加该结点的权值之后形成的新的线段树 c[ro ... 
- 网络赛 I题 Max answer  单调栈+线段树
		题目链接:https://nanti.jisuanke.com/t/38228 题意:在给出的序列里面找一个区间,使区间最小值乘以区间和得到的值最大,输出这个最大值. 思路:我们枚举每一个数字,假设是 ... 
- ACM-ICPC 2018 南京赛区网络预赛 G Lpl and Energy-saving Lamps(线段树)
		题目链接:https://nanti.jisuanke.com/t/30996 中文题目: 在喝茶的过程中,公主,除其他外,问为什么这样一个善良可爱的龙在城堡里被监禁Lpl?龙神秘地笑了笑,回答说这是 ... 
随机推荐
- python6.2类的封装
			class Card(object): def __init__(self,num,pwd,ban): self.num=num#卡号 self.pwd=pwd#密码 self.__ban=ban#余 ... 
- qt事件过滤器的使用(可以用于控制屏幕背光等)
			在嵌入式qt项目中,有时并不需求屏幕一直亮着,需要一段时间不操作时,将屏幕背光关掉,以达到节能的目的: 在qt项目中,可以通过重写事件过滤器来实现屏幕操作的检测,加上定时器的时间控制,可以实现指定时间 ... 
- 精讲RestTemplate第4篇-DELETE、PUT等请求方法使用详解
			本文是精讲RestTemplate第5篇,前篇的blog访问地址如下: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何使用 精讲RestTemplate第2篇-多种底层H ... 
- C#LeetCode刷题之#447-回旋镖的数量(Number of Boomerangs)
			问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3792 访问. 给定平面上 n 对不同的点,"回旋镖&q ... 
- Window  C盘 占满原因之一
			最近一段时间,突然C盘 莫名奇妙的满了 ,也没有中毒. 最后查找是因为安装了SQL Reporting 的原因 C:\Program Files\Microsoft SQL Server Repor ... 
- 面试中的老大难-mysql事务和锁,一次性讲清楚!
			众所周知,事务和锁是mysql中非常重要功能,同时也是面试的重点和难点.本文会详细介绍事务和锁的相关概念及其实现原理,相信大家看完之后,一定会对事务和锁有更加深入的理解. 本文主要内容是根据掘金小册& ... 
- Java并发-Synchronized关键字
			一.多线程下的i++操作的并发问题 package passtra; public class SynchronizedDemo implements Runnable{ private static ... 
- 【CF1174D】 Ehab and the Expected XOR Problem - 构造
			题面 Given two integers \(n\) and \(x\), construct an array that satisfies the following conditions: · ... 
- 旧 WCF 项目成功迁移到 asp.net core web api
			背景 接上一篇,放弃了 asp.net core + gRPC 的方案后,我灵光一闪,为什么不用 web api 呢?不也是 asp.net core 的吗?虽然 RESTful 不是强约束,客户端写 ... 
- python header设置随机user_agent
			1 安装 fake_useragent pip install fake_useragent 2 使用 # -*- coding:utf-8 -*- from fake_useragent impor ... 
