后缀数组+RMQ+二分
后缀数组二分确定第K不同子串的位置 , 二分LCP确定可选的区间范围 , RMQ求范围内最小的sa
aaa 4 0 2 3 5
1 1 1 3 1 2 0 0
#include<iostream> #include<cstring> #include<cstdio> #include<cmath> using namespace std; #define prt(k) cout<<#k" = "<<k<<endl; const int N = 100010; int sa[N], rank[N], rank2[N], h[N],c[N], *x, *y, ans[N]; typedef long long ll; char str[N]; bool cmp(int* r, int a, int b, int l, int n) { return r[a]==r[b] && a+l<n && b+l<n && r[a+l]==r[b+l]; } void radix_sort(int n,int sz) { for(int i=0; i<sz; i++) c[i]=0; for(int i=0; i<n; i++) c[x[y[i]]]++; for(int i=1; i<sz; i++) c[i]+=c[i-1]; for(int i=n-1; i>=0; i--) sa[--c[x[y[i]]]] = y[i]; } void get_sa(char c[],int n,int sz=128) { x=rank,y=rank2; for(int i=0;i<n;i++) x[i]=c[i],y[i]=i; radix_sort(n,sz); for(int len=1;len<n;len<<=1) { int yid=0; for(int i=n-len;i<n;i++) y[yid++]=i; for(int i=0;i<n;i++) if(sa[i]>=len) y[yid++]=sa[i]-len; radix_sort(n,sz); swap(x,y); x[sa[0]]=yid=0; for(int i=1;i<n;i++) { x[sa[i]]=cmp(y,sa[i],sa[i-1],len,n) ? yid : ++yid; } sz=yid+1; if(sz>=n) break; } for(int i=0;i<n;i++) rank[i]=x[i]; } void get_h(char str[],int n) { int k=0; h[0]=0x3f3f3f3f; for(int i=0;i<n;i++) { if(rank[i]==0) continue; k=max(k-1,0); int j=sa[rank[i]-1]; while(i+k<n && j+k<n && str[i+k]==str[j+k]) k++; h[rank[i]]=k; } } int dp[N][20]; int mmm[N][22]; void RMQ_init(int n) { for(int i=0;i<n;i++) dp[i][0]=h[i], mmm[i][0]=sa[i]; dp[0][0]=0x3f3f3f3f; for(int i=1;(1<<i)<=n;i++) { for(int j=0;j+(1<<i)-1<n; j++) dp[j][i]=min(dp[j][i-1], dp[j+(1<<(i-1))][i-1]), mmm[j][i]=min(mmm[j][i-1], mmm[j+(1<<(i-1))][i-1]); } } int LCP(int l,int r,int n) { if(l==r) return n-sa[l]; l++; if(l>r) swap(l,r); int k = 0; while(1<<(k+1) <= r-l+1) k++; return min(dp[l][k],dp[r-(1<<k)+1][k]); } ll Range[N]; int bin(ll x, int n) { int ans = -1; int l=0, r=n-1, mid; while(l<=r) { mid=(l+r)/2; if(Range[mid]<x) ans=mid,l=mid+1; else r=mid-1; } return ans; } int MMM(int l, int r) { if(l>r) swap(l,r); int k = 0; while(1<<(k+1) <= r-l+1) k++; return min(mmm[l][k], mmm[r-(1<<k)+1][k]); } int binID(int x,int n,int len) { int ans=x; int l=x,r=n-1,mid; while(l<=r) { mid=(l+r)/2; if(LCP(x,mid,n)>=len) { ans=mid; l=mid+1; } else r=mid-1; } return ans; } int main() { while(scanf("%s",str)==1) { int n=strlen(str); get_sa(str,n); get_h(str,n); RMQ_init(n); h[0]=0; for(int i=0;i<n;i++) { Range[i] = (n-sa[i])-h[i]; if(i-1>=0) Range[i]+=Range[i-1]; } int q; cin>>q; int L=0,R=0; while(q--) { ll V; scanf("%I64d",&V); ll K = (L^R^V) + 1; if(K>Range[n-1]) { L=0, R=0; printf("0 0\n"); continue; } int id = bin(K,n); ll jian=0; if(id>=0) jian=Range[id]; ll res=K-jian; id++; int len=h[id]+res; int hid=binID(id,n,len); int Left=MMM(id,hid); L=Left+1, R=Left+len; printf("%d %d\n",L,R); } } }