题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6703
#include <bits/stdc++.h>
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define per(i, a, b) for(int i = (a); i >= (b); i++)
#define ls (o<<1)
#define rs (o<<1|1)
#define mid ((l+r)>>1)
using namespace std;
const int N = 1e5+1000;
const int SIZE = 256;
//-----------------------------------------------------
int cntA[N],cntB[N],sa[N],tsa[N],A[N],B[N],height[N],Rank[N],bucket[SIZE];
int n;
char s[N];
void get_SA(char *ch) {
for(int i = 0; i < SIZE; i++) bucket[i] = 0;
rep(i, 1, n) bucket[ch[i-1]]++;
rep(i, 1, SIZE-1) bucket[i] += bucket[i-1];
for(int i = n; i; i--) sa[bucket[ch[i-1]]--] = i;
Rank[sa[1]] = 1;
for(int i = 2; i <= n; i++) {
Rank[sa[i]] = Rank[sa[i-1]];
if(ch[sa[i]-1]!=ch[sa[i-1]-1]) Rank[sa[i]]++;
}
for(int l = 1;Rank[sa[n]] < n; l<<=1) {
memset(cntA,0,sizeof(cntA));
memset(cntB,0,sizeof(cntB));
for(int i = 1; i <= n; i++) {
cntA[A[i] = Rank[i]]++;
cntB[B[i] = (i+l<=n) ? Rank[i+l]:0]++;
}
for(int i = 1; i <= n; i++) cntB[i] += cntB[i-1];
for(int i = n; i; i--) tsa[cntB[B[i]]--] = i;
for(int i = 1; i <= n; i++) cntA[i] += cntA[i-1];
for(int i = n; i; i--) sa[cntA[A[tsa[i]]]--] = tsa[i];
Rank[sa[1]] = 1;
for(int i = 2; i <= n; i++) {
Rank[sa[i]] = Rank[sa[i-1]];
if(A[sa[i]] != A[sa[i-1]] || B[sa[i]] != B[sa[i-1]]) Rank[sa[i]]++;
}
}
for(int i = 1, j=0; i <= n; i++) {
if(j) j--;
while(ch[i+j-1]==ch[sa[Rank[i]-1]+j-1]) j++;
height[Rank[i]] = j;
}
}
//-----------------------------------------------------
int mt[4*N];
void build(int o,int l,int r) {
if(l==r) {mt[o]=height[l];return;}
build(ls,l,mid);
build(rs,mid+1,r);
mt[o] = min(mt[ls],mt[rs]);
}
int getL(int o,int l,int r,int x) {
if(l==r) return l;
return mt[rs]<x?getL(rs,mid+1,r,x):getL(ls,l,mid,x);
}
int qL(int o,int l,int r,int ql,int qr,int x) {
if(ql>qr) return -1;
if(qr<l||r<ql) return -1;
if(ql<=l&&r<=qr) return mt[o]<x?getL(o,l,r,x):-1;
int t = qL(rs,mid+1,r,ql,qr,x);
return t!=-1?t:qL(ls,l,mid,ql,qr,x);
}
int getR(int o,int l,int r,int x) {
if(l==r) return l;
return mt[ls]<x?getR(ls,l,mid,x):getR(rs,mid+1,r,x);
}
int qR(int o,int l,int r,int ql,int qr,int x) {
if(ql>qr) return -1;
if(qr<l||r<ql) return -1;
if(ql<=l&&r<=qr) return mt[o]<x?getR(o,l,r,x):-1;
int t = qR(ls,l,mid,ql,qr,x);
return t!=-1?t:qR(rs,mid+1,r,ql,qr,x);
}
//-----------------------------------
struct TREE{
int l,r,x;
}tree[N*30];
int tot,rt[N];
void insert(int &o,int l,int r,int data) {
tree[++tot] = tree[o];
o = tot;
tree[o].x++;
if(l==r) return;
if(mid>=data) insert(tree[o].l,l,mid,data);
else insert(tree[o].r,mid+1,r,data);
}
int query(int lo,int ro,int l,int r,int data) {
if(l==r) return l;
int k = tree[tree[ro].l].x-tree[tree[lo].l].x;
if(k>=data) return query(tree[lo].l,tree[ro].l,l,mid,data);
else return query(tree[lo].r,tree[ro].r,mid+1,r,data-k);
}
//----------------------------------------
int main() {
//freopen("a.txt","r",stdin);
ios::sync_with_stdio(0);
int T;
cin>>T;
while(T--) {
int q;
cin>>n>>q;
cin>>s;
n = strlen(s);
get_SA(s);
tot = 0;
rt[0] = 0;
tree[0].l = tree[0].r = tree[0].x = 0;
rep(i, 1, n) {
rt[i] = rt[i-1];
insert(rt[i],1,n,sa[i]);
}
build(1,1,n);
rep(i, 1, q) {
int l, r, k;
cin>>l>>r>>k;
int len = (r-l+1);
int now = Rank[l];
int R = qR(1,1,n,now+1,n,len);
if(R==-1) R = n;
else R--;
int L = qL(1,1,n,1,now,len);
int ans;
if(k>R-L+1) ans = -1;
else ans = query(rt[L-1],rt[R],1,n,k);
cout<<ans<<endl;
}
}
return 0;
}