题意大概就是给一个串,每次查询q,令k=(q^l^r)+1,其中^表示异或,l,r是上次查询的答案,初始为0,去串中字典序第k小的子串最靠左出现的位置。之前做过一题 SPOJ 的SUBLEX基本和这题一样,不过那题只要找到第k小的字符串就行了,这题需要找到这个子串最靠右出现的位置。考虑找到第k小的子串,直接拿原串先构造后缀数组,统计一下第i个后缀有多少个不同的前缀num[i](也就是在原串中有多少个不重复的子串),按sa排序后,这些连续出现的子串的字典序也是相同的,那么对num[i]求前缀和后就可以去二分一个位置,找到字典序第k小的子串出现的位置了。这里找到的位置不一定是最靠左的,所以还要在原串中找一下最左的位置,其实到了这里,直接两个指针,一个向前一个向后,暴力找到最长的连续的height[i]>=目标子串长度 的位置下标L,R,然后RMQ(L,R,sa)找到最小的位置就好了,当然极限数组(例如10W个a)肯定会TLE的,但它居然能过...而且还更快一点,果然是数据太弱了- =...当然,本着严(zi)谨(nue)的态度,好孩子不要学这种方法。一种可行的做法,确定了当前的位置pos,我们要做的就是在pos后面找个R,前面找个L使得[L,R]这个区间的height的最小值>=目标子串的长度,那么可以直接在[POS,n]中二分处位置R,同样在[1,POS]中二分出L,由于RMQ预处理后查询是O(1),所以两边logN的二分就可以找到答案的区间[L,R],最后再RMQ一下就得到最后的答案了。注意这里求区间的RMQ和求答案的RMQ是查询的两个数组,要分别初始化...
/*=============================================================================
# Author:Erich
# FileName:
=============================================================================*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <queue>
#include <stack>
#define lson id<<1,l,m
#define rson id<<1|1,m+1,r
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const ll INF=1ll<<60;
const double PI=acos(-1.0);
const int maxn=205000;
const int mod=1e9+7;
char ss[maxn];
int belong[maxn];
int s[maxn],rs[maxn];
int sa[maxn],t[maxn],t2[maxn],c[maxn];
int n,m,tt;
int rank[maxn],height[maxn];
int len,l;
inline int idx(char c)
{
return c-'a'+1;
}
inline char fdx(int x)
{
return char(x-1+'a');
}
void getheight(int n)
{
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 build_ss(int m,int n)
{
n++;
int i,*x=t,*y=t2;
for (int i=0; i<m; i++) c[i]=0;
for (int i=0; i<n; i++) c[x[i]=s[i]]++;
for (int i=1; i<m; i++) c[i]+=c[i-1];
for (int 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=1; 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 d[2][maxn][50];
int LOG[maxn];
int RMQ_init(int x,int A[])
{
for(int i=1; i<=n; i++) d[x][i][0]=A[i];
for (int j=1; (1<<j)<=n; j++)
for (int i=1; i+(1<<j)-1<=n; i++)
d[x][i][j]=min(d[x][i][j-1],d[x][i+(1<<(j-1))][j-1]);
}
int RMQ(int x,int L,int R)
{
int k=LOG[R-L+1];
return min(d[x][L][k],d[x][R-(1<<k)+1][k]);
}
ll num[maxn];
int main()
{
// freopen("in.txt","r",stdin);
int k=0;
for (int i=0; i<105000; i++)
{
while((1<<(k+1))<=i) k++;
LOG[i]=k;
}
while(~scanf("%s",ss))
{
int l=strlen(ss);
for(int i=0; i<l; i++)
s[i]=idx(ss[i]);
n=l;
s[n]=0;
build_ss(33,n);
getheight(n);
for (int i=0; i<=n; i++)
num[i]=n-sa[i];
for (int i=1; i<=n; i++)
num[i]-=height[i];
for (int i=1; i<=n; i++)
num[i]+=num[i-1];
ll tot=num[n];
scanf("%d",&m);
ll la=0,lb=0;
ll k;
RMQ_init(0,height);
RMQ_init(1,sa);
while(m--)
{
scanf("%I64d",&k);
k^=la;
k^=lb;
k++;
if (k>=1 && k<=tot)
{
int pos=lower_bound(num+1,num+1+n,k)-num;
int len=k-num[pos-1]+height[pos];
int l=pos+1,r=n;
int mid;
int L,R;
while(l<r)
{
mid=(l+r)>>1;
if (RMQ(0,pos+1,mid)>=len) l=mid+1;
else r=mid;
}
if (RMQ(0,pos+1,l)>=len) R=l;
else R=l-1;
l=1; r=pos;
while(l<r)
{
mid=(l+r)>>1;
if (RMQ(0,mid,pos)>=len) r=mid;
else l=mid+1;
}
if (RMQ(0,l,pos)>=len) L=l-1;
else L=l;
la=RMQ(1,L,R);
lb=la+len-1;
la++;
lb++;
printf("%I64d %I64d\n",la,lb);
}
else
{
la=lb=0;
puts("0 0");
}
}
}
return 0;
}