Problem Description
You are given a string S consisting of only lowercase english letters and some queries.
For each query (l,r,k), please output the starting position of the k-th occurence of the substring SlSl+1...Sr in S.
For each query (l,r,k), please output the starting position of the k-th occurence of the substring SlSl+1...Sr in S.
Input
The first line contains an integer T(1≤T≤20), denoting the number of test cases.
The first line of each test case contains two integer N(1≤N≤105),Q(1≤Q≤105), denoting the length of S and the number of queries.
The second line of each test case contains a string S(|S|=N) consisting of only lowercase english letters.
Then Q lines follow, each line contains three integer l,r(1≤l≤r≤N) and k(1≤k≤N), denoting a query.
There are at most 5 testcases which N is greater than 103.
The first line of each test case contains two integer N(1≤N≤105),Q(1≤Q≤105), denoting the length of S and the number of queries.
The second line of each test case contains a string S(|S|=N) consisting of only lowercase english letters.
Then Q lines follow, each line contains three integer l,r(1≤l≤r≤N) and k(1≤k≤N), denoting a query.
There are at most 5 testcases which N is greater than 103.
Output
For each query, output the starting position of the k-th occurence of the given substring.
If such position don't exists, output −1 instead.
If such position don't exists, output −1 instead.
Sample Input
2
12 6
aaabaabaaaab
3 3 4
2 3 2
7 8 3
3 4 2
1 4 2
8 12 1
1 1
a
1 1 1
Sample Output
5
2
-1
6
9
8
1
思路:
我们要找l~r的字串的兄弟串不难想到求lcp 通过二分我们可以找到最右和最左的排名 然后我们只要用可持久线段树维护下标 然后求下标第k小的字符串即可
#include <bits/stdc++.h> using namespace std; const double pi = acos(-1.0); const int N = 1e5+1000; const int inf = 0x3f3f3f3f; const double eps = 1e-6; typedef long long ll; const ll mod = 1e9+7; int rt[N]; struct tree{ int l,r,v,ls,rs; }t[N<<5]; int nico; void build(int &p,int l,int r){ p=++nico; t[p].l=l; t[p].r=r; if(l==r){ return ; } int mid=(l+r)>>1; build(t[p].ls,l,mid); build(t[p].rs,mid+1,r); } void update(int &p,int last,int x){ p=++nico; t[p]=t[last]; t[p].v++; if(t[p].l==t[p].r&&t[p].l==x){ t[p].v=1; return ; } int mid=(t[p].l+t[p].r)>>1; if(x<=mid) update(t[p].ls,t[last].ls,x); else update(t[p].rs,t[last].rs,x); } int query(int p,int last,int k){ if(t[p].l==t[p].r){ return t[p].l; } int tmp=t[t[p].ls].v-t[t[last].ls].v; int mid=(t[p].l+t[p].r)>>1; if(tmp>=k) return query(t[p].ls,t[last].ls,k); else return query(t[p].rs,t[last].rs,k-tmp); } struct S_array{ int s[N],sa[N],t[N],t2[N],c[N],n; int f[N][20]; void build_sa(int m){ int i,*x=t,*y=t2; for(i=0;i<m;i++)c[i]=0; for(i=0;i<n;i++)c[x[i]=s[i]]++; for(i=1;i<m;i++)c[i]+=c[i-1]; for(i=n-1;i>=0;i--)sa[--c[x[i]]]=i; for(int k=1;k<=n;k<<=1){ int p=0; for(i=n-k;i<n;i++)y[p++]=i; for(i=0;i<n;i++)if(sa[i]>=k)y[p++]=sa[i]-k; for(i=0;i<m;i++)c[i]=0; for(i=0;i<n;i++)c[x[y[i]]]++; for(i=0;i<m;i++)c[i]+=c[i-1]; for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i]; swap(x,y); p=1;x[sa[0]]=0; for(i=1;i<n;i++) x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++; if(p>=n)break; m=p; } } int rank[N],height[N]; void getHeight(){ int i,j,k=0; for(i=0;i<n;i++)rank[sa[i]]=i; for(i=0;i<n;i++){ if(k)k--; int j=sa[rank[i]-1]; while(s[i+k]==s[j+k])k++; height[rank[i]]=k; } } void rmq(){ for(int i=1;i<n;i++) f[i][0]=height[i]; for(int j=1;j<20;j++) for(int i=1;i+(1<<j)-1<n;i++) f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]); } int lcp(int l,int r){ int k=log2(r-l+1); return min(f[l][k],f[r+1-(1<<k)][k]); } void bu(){ for(int i=1;i<n;i++) update(rt[i],rt[i-1],sa[i]); } int work(int l,int r,int k){ int po=rank[l-1]; //cout<<po<<endl; int L,R,ans=-1; int mxl,mxr; L=1; R=po; mxl=mxr=po; while(L<=R){ int mid=(L+R)>>1; // cout<<L<<" "<<R<<" "<<mid<<" "<<lcp(mid,po)<<endl; if(lcp(mid,po)>=r-l+1){ R=mid-1; ans=mid; }else{ L=mid+1; } } if(ans!=-1) mxl=ans; ans=-1; if(po<n-1){ L=po+1; R=n-1; while(L<=R){ // cout<<L<<" "<<R<<endl; int mid=(L+R)>>1; if(lcp(po+1,mid)>=r-l+1){ L=mid+1; ans=mid; }else{ R=mid-1; } } if(ans!=-1) mxr=ans; } // cout<<n<<endl; // cout<<mxl<<" "<<mxr<<endl; if(lcp(mxl,mxr)>=r-l+1){ mxl=mxl-1; } if(mxr-mxl+1<k) return -1; return query(rt[mxr],rt[mxl-1],k)+1; } }sa; char s[N]; int main(){ // ios::sync_with_stdio(false); // cin.tie(0); cout.tie(0); int t; scanf("%d",&t); while(t--){ int n,q; scanf("%d%d",&n,&q); scanf("%s",s); nico=0; for(int i=0;i<n;i++) sa.s[i]=s[i]-'a'+1; sa.s[n]=0; sa.n=n+1; sa.build_sa(27); sa.getHeight(); build(rt[0],0,N); sa.rmq(); sa.bu(); for(int i=1;i<=q;i++){ int l,r,k; scanf("%d%d%d",&l,&r,&k); printf("%d ",sa.work(l,r,k)); } } }