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
Source
Recommend
SOLUTION:
算板子吧,很好理解
CODE:
#include<bits/stdc++.h> using namespace std; int n,q; const int N = 3e5+10; char s[N]; int sa[N],c[N]; int t1[N],t2[N]; int height[N]; int r[N]; int RMQ[N]; int mm[N]; int best[50][N]; int Rank[N]; void da(int m ) { int i,*x=t1,*y=t2; for(i = 1; i <= m; i++) c[i] = 0; for(i = 1; i <= n; i++) c[x[i] = s[i]]++; for(i = 1; i <= m; i++) c[i] += c[i - 1]; for(i = n; i >= 1; i--) sa[c[x[i]]--] = i; for(int k = 1; k <= n; k <<= 1) { int p = 0; for(i = n - k + 1; i <= n; i++) y[++p] = i; for(i = 1; i <= n; i++) if(sa[i] > k) y[++p] = sa[i] - k; for(i = 1; i <= m; i++) c[i] = 0; for(i = 1; i <= n; i++) c[x[y[i]]]++; for(i = 1; i <= m; i++) c[i] += c[i - 1]; for(i = n; i >= 1; i--) sa[c[x[y[i]]]--] = y[i]; swap(x, y); p = 1; x[sa[1]] = 1; for(i = 2; i <= n; i++) x[sa[i]] = (y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k]) ? p : ++p; if(p >= n) break; m = p; } } void getheight() { int i, j, k = 0; for(i = 1; i <= n; i++) Rank[sa[i]] = i; for(i = 1; i <= n; i++) { if(k) k--; j=sa[Rank[i] - 1]; while(s[j+k] == s[i+k]) k++; height[Rank[i]] = k; } } void initrmq(int n) { mm[0]=-1; for(int i=1; i<=n; i++) mm[i]=((i&(i-1))==0)?mm[i-1]+1:mm[i-1]; for(int i=1; i<=n; i++)best[0][i]=i; for(int i=1; i<=25; i++) { for(int j=1; j+(1<<i)-1<=n; j++) { int a=best[i-1][j]; int b=best[i-1][j+(1<<(i-1))]; if(RMQ[a]<RMQ[b])best[i][j]=a; else best[i][j]=b; } } } int askRMQ(int a,int b) { int t; t=mm[b-a+1]; b-=(1<<t)-1; a=best[t][a]; b=best[t][b]; return RMQ[a]<RMQ[b]?a:b; } int lcp(int a,int b) { a=Rank[a],b=Rank[b]; if(a>b)swap(a,b); return height[askRMQ(a+1,b)]; } int tr[N*70],tot,root[N]; int ls[N*70],rs[N*70]; void cha(int y,int &x,int l,int r,int p) { x=++tot; tr[x]=tr[y]+1; ls[x]=ls[y],rs[x]=rs[y]; if(l==r)return ; int mid=l+r>>1; if(p<=mid)cha(ls[y],ls[x],l,mid,p); else cha(rs[y],rs[x],mid+1,r,p); } int que(int y,int x,int l,int r,int k) { if(l==r)return l; int mid=l+r>>1; int sum=tr[ls[x]]-tr[ls[y]]; if(k<=sum)return que(ls[y],ls[x],l,mid,k); else return que(rs[y],rs[x],mid+1,r,k-sum); } void Build() { tot=0; memset(tr,0,sizeof tr); memset(root,0,sizeof root); memset(ls,0,sizeof ls); memset(rs,0,sizeof rs); for(int i=1; i<=n; i++) cha(root[i-1],root[i],1,n,sa[i]); } signed main() { int T; cin>>T; #define sc(x) scanf("%d",&(x)) while(T--) { sc(n); sc(q); memset(s,0,sizeof s); scanf("%s",s+1); int len=strlen(s+1); da(250); getheight(); memset(RMQ,0,sizeof RMQ); for(int i=1; i<=n; i++)RMQ[i]=height[i]; initrmq(n); Build(); while(q--) { int l,r,k; sc(l);sc(r);sc(k); int len=r-l+1; int up=-1,down=-1; int L,R; R=Rank[l]-1; L=1; up=Rank[l]; while(L<=R) { int mid=L+R>>1; if(lcp(sa[mid],sa[Rank[l]])<len) { L=mid+1; } else { R=mid-1; up=mid; } } L=Rank[l]+1; R=n; down=Rank[l]; while(L<=R) { int mid=L+R>>1; if(lcp(sa[mid],sa[Rank[l]])<len) { R=mid-1; } else { L=mid+1; down=mid; } } int x=root[up-1]; int y=root[down]; if(tr[y]-tr[x]<k || down<up) { puts("-1");continue; } int ans=que(x,y,1,n,k); cout<<ans<<endl; } } }