通过后缀数组可以找到第K的串,然后用二分找到最左边的编号。。。
#include <iostream> #include <queue> #include <stack> #include <map> #include <set> #include <bitset> #include <cstdio> #include <algorithm> #include <cstring> #include <climits> #include <cstdlib> #include <cmath> #include <time.h> #define maxn 100005 #define maxm 40005 #define eps 1e-10 #define mod 1000000007 #define INF 999999999 #define lowbit(x) (x&(-x)) #define mp mark_pair #define ls o<<1 #define rs o<<1 | 1 #define lson o<<1, L, mid #define rson o<<1 | 1, mid+1, R typedef long long LL; //typedef int LL; using namespace std; LL qpow(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base;base=base*base;b/=2;}return res;} LL powmod(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base%mod;base=base*base%mod;b/=2;}return res;} void scanf(int &__x){__x=0;char __ch=getchar();while(__ch==' '||__ch=='\n')__ch=getchar();while(__ch>='0'&&__ch<='9')__x=__x*10+__ch-'0',__ch = getchar();} LL gcd(LL _a, LL _b){if(!_b) return _a;else return gcd(_b, _a%_b);} // head char s[maxn]; int sa[maxn], c[maxn], t1[maxn], t2[maxn]; int rank[maxn], height[maxn]; void build(int n, int m) { int *x = t1, *y = t2, p; 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) { p = 0; for(int i = n-k; i < n; i++) y[p++] = i; for(int i = 0; i < n; i++) if(sa[i] >= k) y[p++] = sa[i] - k; for(int i = 0; i < m; i++) c[i] = 0; for(int i = 0; i < n; i++) c[x[y[i]]]++; for(int i = 1; i < m; i++) c[i] += c[i-1]; for(int i = n-1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i]; p = 1, swap(x, y), x[sa[0]] = 0; for(int i = 1; i < n; i++) x[sa[i]] = y[sa[i]] == y[sa[i-1]] && y[sa[i] + k] == y[sa[i-1] + k] ? p-1 : p++; if(p >= n) break; m = p; } } void getheight(int n) { int k = 0; for(int i = 0; i <= n; i++) rank[sa[i]] = i; for(int 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; } } int p[maxn]; LL st1[maxn][20], st2[maxn][20]; LL sum[maxn]; void init(int n, int *a, LL (*t)[20]) { p[0] = -1; for(int i = 1; i <= n; i++) p[i] = i & (i-1) ? p[i-1] : p[i-1] + 1; for(int i = 1; i <= n; i++) t[i][0] = a[i]; for(int j = 1; j <= p[n]; j++) for(int i = 1; i + (1 << j) - 1 <= n; i++) t[i][j] = min(t[i][j-1], t[i + (1 << (j-1))][j-1]); } LL query(int l, int r, LL (*t)[20]) { LL k = p[r - l + 1]; return min(t[l][k], t[r - (1 << k) + 1][k]); } LL lcp(int a, int b) { if(a > b) swap(a, b); return query(a+1, b, st1); } int find(int n, LL x) { LL bot = 0, top = n, mid, res; while(top >= bot) { mid = (top + bot) >> 1; if(sum[mid] >= x) top = mid - 1, res = mid; else bot = mid + 1; } return res; } int search(int pos, int n, LL k) { int bot = pos + 1, top = n, mid, res = -1; while(top >= bot) { mid = (top + bot) >> 1; if(lcp(pos, mid) < k) top = mid - 1; else bot = mid + 1, res = mid; } if(res != -1) return query(pos, res, st2) + 1; return sa[pos] + 1; } void work(void) { int n = strlen(s), l, r, kk, now, tmp; LL k, v; build(n+1, 128); getheight(n); init(n, height, st1); init(n, sa, st2); sum[0] = l = r = 0; for(int i = 1; i <= n; i++) sum[i] = n - sa[i] - height[i]; for(int i = 1; i <= n; i++) sum[i] += sum[i-1]; scanf("%d", &kk); while(kk--) { scanf("%I64d", &v); k = (l ^ r ^ v) + 1; if(k > sum[n]) printf("0 0\n"), l = r = 0; else { now = find(n, k); tmp = k - sum[now-1] + height[now]; l = min(sa[now] + 1, search(now, n, tmp)); r = l + tmp - 1; printf("%d %d\n", l, r); } } } int main(void) { while(scanf("%s", s)!=EOF) work(); return 0; }