題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=6704
思路:對於每個包含前綴的endpos求出它所代表的子串第一次出現的位置,對於每次詢問,找到子串對應的endpos所在位置,
然後就相當於查詢當前節點子樹第k大的值是什麼,dfs序然後主席樹就行了
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <bitset>
#include <cmath>
#include <cctype>
#include <unordered_map>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <sstream>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll inff = 0x3f3f3f3f3f3f3f3f;
#define FOR(i,a,b) for(int i(a);i<=(b);++i)
#define FOL(i,a,b) for(int i(a);i>=(b);--i)
#define REW(a,b) memset(a,b,sizeof(a))
#define inf int(0x3f3f3f3f)
#define si(a) scanf("%d",&a)
#define sl(a) scanf("%lld",&a)
#define sd(a) scanf("%lf",&a)
#define ss(a) scanf("%s",a)
#define mod ll(998244353)
#define pb push_back
#define eps 1e-7
#define lc d<<1
#define rc d<<1|1
#define Pll pair<ll,ll>
#define P pair<int,int>
#define pi acos(-1)
const int MAXN=1e5+8;
char a[MAXN];
struct as{
int l,r,sum;}tr[MAXN*40];
int rt[MAXN<<1],qw,n,q,l,r,k,sa,head[MAXN<<1];
struct node{
int next,to;}e[MAXN<<2];
void add2(int a,int b)
{
e[sa].next=head[a];
e[sa].to=b;
head[a]=sa++;
}
void add1(int l,int r,int &x,int y,int pos)
{
tr[++qw]=tr[y],tr[qw].sum++,x=qw;
if(l==r) return;
int mid=(l+r)>>1;
if(mid>=pos) add1(l,mid,tr[x].l,tr[y].l,pos);
else add1(mid+1,r,tr[x].r,tr[y].r,pos);
}
int query(int l,int r,int x,int y,int k)
{
if(l==r)
{
if(k==1) return l;
else return inf;
}
int mid=(l+r)>>1;
int sum=tr[tr[y].l].sum-tr[tr[x].l].sum;
if(sum>=k) return query(l,mid,tr[x].l,tr[y].l,k);
else return query(mid+1,r,tr[x].r,tr[y].r,k-sum);
}
struct SAM{
int las=1,tot=1,ch[MAXN<<1][26],len[MAXN<<1],fa[MAXN<<1][19];
int sz[MAXN<<1],id[MAXN<<1],cnt,fpos[MAXN<<1],er[MAXN<<1],num[MAXN<<1];
void init()
{
FOR(i,1,tot) memset(ch[i],0,sizeof(ch[i])),head[i]=-1;
las=tot=1;cnt=0;
}
inline void add(int c,int z)
{
int p=las;int np=las=++tot;
len[np]=len[p]+1;fpos[np]=len[np];er[z]=np;
for(;p&&!ch[p][c];p=fa[p][0]) ch[p][c]=np;
if(!p) fa[np][0]=1;
else
{
int q=ch[p][c];
if(len[q]==len[p]+1) fa[np][0]=q;
else
{
int nq=++tot;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
len[nq]=len[p]+1;
fa[nq][0]=fa[q][0];
fpos[nq]=n+1;
fa[q][0]=fa[np][0]=nq;
for(;p&&ch[p][c]==q;p=fa[p][0]) ch[p][c]=nq;
}
}
}
void dfs(int u)
{
sz[u]=1;id[++cnt]=u;num[u]=cnt;
for(int i=head[u];i!=-1;i=e[i].next)
{
dfs(e[i].to);
sz[u]+=sz[e[i].to];
}
}
void bz()
{
FOR(i,1,18)
FOR(j,1,tot)
fa[j][i]=fa[fa[j][i-1]][i-1];
}
int getsz(int u,int z)
{
FOL(i,18,0)
{
int v=fa[u][i];
if(len[v]>=z) u=v;
}
return u;
}
inline void slove()
{
sa=0;
FOR(i,2,tot) add2(fa[i][0],i);
dfs(1);qw=0;bz();int ans;
FOR(i,1,cnt) add1(1,n+1,rt[i],rt[i-1],fpos[id[i]]);
while(q--)
{
si(l),si(r),si(k);
int pos=getsz(er[r],r-l+1);
ans=query(1,n+1,rt[num[pos]-1],rt[num[pos]+sz[pos]-1],k);
if(ans>=n+1) ans=-1;
if(ans!=-1) ans-=(r-l);
printf("%d\n",ans);
}
}
}sam;
int main()
{
cin.tie(0);
cout.tie(0);
int t;
cin>>t;
REW(head,-1);
while(t--)
{
sam.init();
cin>>n>>q;ss(a);
for(int i=0;i<n;i++) sam.add(a[i]-'a',i+1);
sam.slove();
}
return 0;
}