Boring String Problem
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 927 Accepted Submission(s): 263
Problem Description
In this problem, you are given a string s and q queries.
For each query, you should answer that when all distinct substrings of string s were sorted lexicographically, which one is the k-th smallest.
A substring s i...j of the string s = a 1a 2 ...a n(1 ≤ i ≤ j ≤ n) is the string a ia i+1 ...a j. Two substrings s x...y and s z...w are cosidered to be distinct if s x...y ≠ S z...w
For each query, you should answer that when all distinct substrings of string s were sorted lexicographically, which one is the k-th smallest.
A substring s i...j of the string s = a 1a 2 ...a n(1 ≤ i ≤ j ≤ n) is the string a ia i+1 ...a j. Two substrings s x...y and s z...w are cosidered to be distinct if s x...y ≠ S z...w
Input
The input consists of multiple test cases.Please process till EOF.
Each test case begins with a line containing a string s(|s| ≤ 10 5) with only lowercase letters.
Next line contains a postive integer q(1 ≤ q ≤ 10 5), the number of questions.
q queries are given in the next q lines. Every line contains an integer v. You should calculate the k by k = (l⊕r⊕v)+1(l, r is the output of previous question, at the beginning of each case l = r = 0, 0 < k < 2 63, “⊕” denotes exclusive or)
Each test case begins with a line containing a string s(|s| ≤ 10 5) with only lowercase letters.
Next line contains a postive integer q(1 ≤ q ≤ 10 5), the number of questions.
q queries are given in the next q lines. Every line contains an integer v. You should calculate the k by k = (l⊕r⊕v)+1(l, r is the output of previous question, at the beginning of each case l = r = 0, 0 < k < 2 63, “⊕” denotes exclusive or)
Output
For each test case, output consists of q lines, the i-th line contains two integers l, r which is the answer to the i-th query. (The answer l,r satisfies that s
l...r is the k-th smallest and if there are several l,r available, ouput l,r which with the smallest l. If there is no l,r satisfied, output “0 0”. Note that s
1...n is the whole string)
Sample Input
aaa 4 0 2 3 5
Sample Output
1 1 1 3 1 2 0 0
Source
Recommend
解题思路:
后缀数组lcp求好,直接暴力找就过了。。。
#include <iostream>
#include <cstdio>
#include <cstring>
#define ll long long
#define maxn 100010
using namespace std;
char s[maxn];
int n,k;
int rank[maxn],sa[maxn],tmp[maxn],lcp[maxn];
bool cmp(int x,int y){
if(rank[x]!=rank[y]) return rank[x]<rank[y];
int sx=x+k<=n ? rank[x+k]:-1;
int sy=y+k<=n ? rank[y+k]:-1;
return sx<sy;
}
void build_sa(){
n=strlen(s);
for(int i=0;i<=n;i++){
sa[i]=i;
rank[i]=i<n ? s[i]:-1;
}
for(k=1;k<=n;k<<=1){
sort(sa,sa+n+1,cmp);
tmp[sa[0]]=0;
for(int i=1;i<=n;i++){
tmp[sa[i]]=tmp[sa[i-1]]+(cmp(sa[i-1],sa[i]) ? 1:0);
}
for(int i=0;i<=n;i++) rank[i]=tmp[i];
}
}
void build_lcp(){
n=strlen(s);
for(int i=0;i<=n;i++) rank[sa[i]]=i;
int h=0;
lcp[0]=0;
for(int i=0;i<n;i++){
int j=sa[rank[i]-1];
if(h>0) h--;
for(;j+h<n&&i+h<n;h++){
if(s[j+h]!=s[i+h]) break;
}
lcp[rank[i]-1]=h;
}
}
ll sum[maxn];
int next[maxn];
void solve(){
sum[0]=0;
for(int i=1;i<=n;i++){
sum[i]=sum[i-1]+n-sa[i]-lcp[i-1];
}
int q;
scanf("%d",&q);
int l=0,r=0;
ll v;
memset(next,-1,sizeof next);
for(int i=0;i<q;i++){
scanf("%I64d",&v);
v=(l^r^v)+1;
if(v>sum[n]){
l=0,r=0;
printf("0 0\n");
continue;
}
int p=lower_bound(sum+1,sum+n+1,v)-sum;
r=v-sum[p-1]+lcp[p-1];
l=sa[p];
for(int j=p;j<n;j++){
if(lcp[j]<r) break;
if(sa[j+1]<l) l=sa[j+1];
}
r=l+r-1;
l++,r++;
printf("%d %d\n",l,r);
}
}
int main(){
while(~scanf("%s",s)){
build_sa();
build_lcp();
solve();
}
return 0;
}