代码:
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=100010;
#define F(x) ((x)/3+((x)%3==1?0:tb))
#define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
int wa[maxn*3],wb[maxn*3],wv[maxn*3],wss[maxn*3];
int r[maxn*3],sa[maxn*3];
inline int c0(int*r,int a,int b)
{
return r[a]==r[b]&&r[a+1]==r[b+1]&&r[a+2]==r[b+2];
}
inline int c12(int k,int*r,int a,int b)
{
if(k==2)
{
return r[a]<r[b]||(r[a]==r[b]&&c12(1,r,a+1,b+1));
}
return r[a]<r[b]||(r[a]==r[b]&&wv[a+1]<wv[b+1]);
}
inline void sort(int*r,int*a,int*b,int n,int m)
{
int i;
for(i=0;i<n;++i)
{
wv[i]=r[a[i]];
}
for(i=0;i<m;++i)
{
wss[i]=0;
}
for(i=0;i<n;++i)
{
++wss[wv[i]];
}
for(i=1;i<m;++i)
{
wss[i]+=wss[i-1];
}
for(i=n-1;i>=0;--i)
{
b[--wss[wv[i]]]=a[i];
}
}
void dc3(int*r,int*sa,int n,int m)
{
int i,j,*rn=r+n,*san=sa+n,ta=0,tb=(n+1)/3,tbc=0,p;
r[n]=r[n+1]=0;
for(i=0;i<n;++i)
{
if(i%3)
{
wa[tbc++]=i;
}
}
sort(r+2,wa,wb,tbc,m);
sort(r+1,wb,wa,tbc,m);
sort(r,wa,wb,tbc,m);
for(p=1,rn[F(wb[0])]=0,i=1;i<tbc;++i)
{
rn[F(wb[i])]=c0(r,wb[i-1],wb[i])?p-1:p++;
}
if(p<tbc)
{
dc3(rn,san,tbc,p);
}
else
{
for(i=0;i<tbc;++i)
{
san[rn[i]]=i;
}
}
for(i=0;i<tbc;++i)
{
if(san[i]<tb)
{
wb[ta++]=san[i]*3;
}
}
if(n%3==1)
{
wb[ta++]=n-1;
}
sort(r,wb,wa,ta,m);
for(i=0;i<tbc;++i)
{
wv[wb[i]=G(san[i])]=i;
}
for(i=0,j=0,p=0;i<ta&&j<tbc;++p)
{
sa[p]=c12(wb[j]%3,r,wa[i],wb[j])?wa[i++]:wb[j++];
}
for(;i<ta;++p)
{
sa[p]=wa[i++];
}
for(;j<tbc;++p)
{
sa[p]=wb[j++];
}
}
int Rank[maxn],height[maxn];
inline void da(int*str,int*sa,int*Rank,int*height,int n,int m)
{
for(int i=n;i<n*3;++i)
{
str[i]=0;
}
dc3(str,sa,n+1,m);
int i,j,k=0;
for(i=0;i<=n;++i)
{
Rank[sa[i]]=i;
}
for(i=0;i<n;++i)
{
if(k)
{
--k;
}
j=sa[Rank[i]-1];
while(str[i+k]==str[j+k])
{
++k;
}
height[Rank[i]]=k;
}
}
int mm[maxn],best[20][maxn];
inline void initRMQ(int n)
{
int i,j,a,b;
for(mm[0]=-1,i=1;i<=n;i++)
{
mm[i]=((i&(i-1))==0)?mm[i-1]+1:mm[i-1];
}
for(i=1;i<=n;i++)
{
best[0][i]=i;
}
for(i=1;i<=mm[n];i++)
{
for(j=1;j<=n+1-(1<<i);j++)
{
a=best[i-1][j];
b=best[i-1][j+(1<<(i-1))];
if(height[a]<height[b])
{
best[i][j]=a;
}
else
{
best[i][j]=b;
}
}
}
}
inline int askRMQ(int a,int b)
{
int t=mm[b-a+1];
b-=(1<<t)-1;
a=best[t][a];
b=best[t][b];
return height[a]<height[b]?a:b;
}
inline int lcp(int a,int b)
{
a=Rank[a];
b=Rank[b];
if(a==b)
{
return height[a];
}
if(a>b)
{
swap(a,b);
}
return height[askRMQ(a+1,b)];
}
struct Node
{
int num,lch,rch;
Node():num(0),lch(-1),rch(-1){}
}tree[maxn*20];
int tot,rt[maxn];
#define init() tot=0
inline void pushup(int p)
{
tree[p].num=tree[tree[p].lch].num+tree[tree[p].rch].num;
}
int build(int l,int r)
{
int p=tot++;
tree[p]=Node();
if(l==r)
{
tree[p].num=0;
return p;
}
int mid=(l+r)>>1;
tree[p].lch=build(l,mid);
tree[p].rch=build(mid+1,r);
pushup(p);
return p;
}
int add(int p,int l,int r,int x,int y,int z)
{
int cp=tot++;
tree[cp]=Node();
if(x<=l&&r<=y)
{
tree[cp].num=tree[p].num+r-l+1;
return cp;
}
int mid=(l+r)>>1;
if(x<=mid)
{
tree[cp].lch=add(tree[p].lch,l,mid,x,y,z);
}
else
{
tree[cp].lch=tree[p].lch;
}
if(mid<y)
{
tree[cp].rch=add(tree[p].rch,mid+1,r,x,y,z);
}
else
{
tree[cp].rch=tree[p].rch;
}
pushup(cp);
return cp;
}
int query(int x,int y,int l,int r,int k)
{
if(l==r)
{
return l;
}
int left_num=tree[tree[y].lch].num-tree[tree[x].lch].num;
int mid=(l+r)>>1;
if(left_num>=k)
{
return query(tree[x].lch,tree[y].lch,l,mid,k);
}
return query(tree[x].rch,tree[y].rch,mid+1,r,k-left_num);
}
char s[maxn];
inline int get_prev(int pos,int len)
{
int l=1,r=pos,mid;
while(l<r)
{
mid=(l+r)>>1;
if(lcp(sa[mid],sa[pos])>=len)
{
r=mid;
}
else
{
l=mid+1;
}
}
return l;
}
inline int get_suf(int pos,int len,int n)
{
int l=pos,r=n,mid;
while(l<r)
{
mid=(l+r+1)>>1;
if(lcp(sa[mid],sa[pos])>=len)
{
l=mid;
}
else
{
r=mid-1;
}
}
return l;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,q;
scanf("%d%d%s",&n,&q,s);
for(int i=0;i<n;++i)
{
r[i]=s[i]-'a'+1;
}
da(r,sa,Rank,height,n,27);
initRMQ(n);
init();
rt[0]=build(0,n-1);
for(int i=1;i<=n;++i)
{
rt[i]=add(rt[i-1],0,n-1,sa[i],sa[i],sa[i]);
}
int l,r,k;
while(q--)
{
scanf("%d%d%d",&l,&r,&k);
int first=get_prev(Rank[l-1],r-l+1);
int last=get_suf(Rank[l-1],r-l+1,n);
if(last-first+1<k)
{
printf("-1\n");
}
else
{
int ans=query(rt[first-1],rt[last],0,n-1,k);
printf("%d\n",ans+1);
}
}
}
return 0;
}
蔡弈文
全部评论