Topic Link: "Codeforces" 741E. Arpa ' s abnormal DNA and Mehrdad ' s deep interest
Observing the effect of two insertion positions on their rank, it can be found that the 5-segment LCP can be split up, so we'll find a suffix array after we stitch the two strings, and then we can get their rank directly on all the insertion positions.
Then ask can be based on K-block, this problem is done.
Just need to write for a while.
#include <bits/stdc++.h> using namespace std;
typedef pair < int, int > PII;
const int MAXN = 200005;
const int SQR = 300;
struct Query {int L, r, X, Y, idx;};
/*===============sa================*/int SA[MAXN], RNK[MAXN], HEIGHT[MAXN];
int T1[MAXN], T2[MAXN], XY[MAXN], C[MAXN];
/*===============sa================*//*===============rmq================*/int dp[MAXN][18];
PII f[maxn][18];
int LOGN[MAXN];
/*===============rmq================*//*==============union===============*/PII Val[MAXN];
int P[MAXN];
/*==============union===============*//*==============main===============*/Char S1[MAXN], S2[MAXN];
int S[MAXN], N, N1, N2;
int IDX[MAXN], RIDX[MAXN];
Vector < Query > SMALL[SQR];
Vector < PII > G[MAXN];
PII ANS[MAXN]; /*==============main===============*/Inline int Comp (int*r, int A, int b, int d) {return r[a] = = R[b] && Amp
R[a + d] = = R[b + d]; } inline void Get_height (int n, int k = 0) {for (int i = 0; I <= N; + + i) rnk[sa[i]] = i;
for (int i = 0; i < n; + + i) {if (k)-K;
Int j = Sa[rnk[i]-1];
while (S[i + K] = = S[j + K]) + + K;
Height[rnk[i]] = k;
} inline int da (int n, int m = 128) {int *x = t1, *y = t2, I, d = 1, p = 0;
for (i = 0; i < m; + i) c[i] = 0;
for (i = 0; i < n; + + i) c[x[i] = S[i]] + +;
for (i = 1; i < m + i) c[i] + = c[i-1];
for (i = n-1 i >= 0;--i) sa[--c[x[i]] = i;
for (; p < n; d <<= 1, m = p) {for (P = 0, i = n-d; i < n; + + i) Y[p + +] = i;
for (i = 0; i < n; + i) if (Sa[i] >= D) y[p + +] = sa[i]-D;
for (i = 0; i < m; + i) c[i] = 0;
for (i = 0; i < n; + + i) c[xy[i] = X[y[i]]] + +;
for (i = 1; i < m + i) c[i] + = c[i-1];
for (i = n-1 i >= 0;--i) sa[--c[xy[i]] = y[i]; Swap (x, y);
p = 0;
X[sa[0]] = p + +; for (i = 1; i < n; + i) x[sa[i]] = Comp (y, sa[i-1], sa[i], D)?
P-1: P + +;
} get_height (n-1);
} inline void init_rmq (int n) {for (int i = 1; I <= n; + i) dp[i][0] = Height[i];
LOGN[1] = 0;
for (int i = 2; I <= n; + + i) logn[i] = Logn[i-1] + (i = = (I & i)); for (int j = 1; (1 << j) < n; + + j) {for (int i = 1; i + (1 << J)-1 <= N; + + i) {dp[i][j] = min (dp[i][j-1],
Dp[i + (1 << (j-1))][j-1]);
}} inline int rmq (int L, int R) {int k = logn[r-l + 1];
return min (dp[l][k], Dp[r-(1 << k) + 1][k]);
inline int LCP (int x, int y) {if (x = = y) return n1-x;
x = rnk[x], y = rnk[y];
if (x > Y) Swap (x, y);
return RMQ (x + 1, y); } inline int GetID (int x, int pos) {if (pos< x) return POS;
if (Pos < x + n2) return n1 + 1 + pos-x;
return pos-n2;
} Inline int cmp (const int& x, const int& y) {int a[6] = {0, x, y, x + n2, Y + n2, n1 + n2};
Sort (A, a + 6);
for (int i = 0; i < 5; + + i) {int T1 = GetID (x, A[i]);
int t2 = GetID (y, a[i]);
int L = A[i] + LCP (t1, T2);
if (L < A[i + 1]) {int t3 = GetID (x, L);
int t4 = GetID (Y, L);
return S[T3] < S[T4];
} return x < y;
} inline void Build () {n1 = strlen (S1);
N2 = strlen (s2);
n = n1 + n2 + 1;
for (int i = 0; i < n1 + i) {s[i] = S1[i];
} S[n1] = ' # ';
for (int i = 0; i < N2 + i) {s[n1 + 1 + i] = s2[i];
} S[n] = 0;
Da (n + 1);
INIT_RMQ (n);
for (int i = 0; I <= n1 + i) {idx[i] = i; Sort (idx, IDX + n1 + 1, CMP);
for (int i = 0; I <= n1 + i) {Ridx[idx[i]] = i;
} inline void Build_big_k () {for (int i = 0; I <= N1; + i) f[i][0] = PII (ridx[i), i);
LOGN[1] = 0;
for (int i = 2; I <= n1 + 1; + + i) logn[i] = Logn[i-1] + (i = = (I & i)); for (int j = 1; (1 << j) < N1; + + j) {for (int i = 0; i + (1 << J)-1 <= n1 + i) {f[i][j] = min (f[i][j-1),
F[i + (1 << (j-1))][j-1]);
inline PII big_rmq (int L, int R) {int k = logn[r-l + 1];
return min (f[l][k], F[r-(1 << k) + 1][k]);
} inline void Calc_big_k (int k, Query x) {PII res (MAXN, MAXN);
for (int i = 0; I <= n1 i = k) {if (i + K <= x.l) continue;
if (X.R < i) break; int L = X.L < I?
X.x:max (x.l% K, x.x); int r = i + K <= x.r? X.y:min (x.r% K, X.y);
if (L > R) continue;
res = min (res, BIG_RMQ (i + L, i + R));
} Ans[x.idx] = res;
int F (int x) {if (p[x] = x) return x;
int lst = F (p[x]);
Val[x] = min (val[x], val[p[x]);
return p[x] = LST;
} inline void Calc_small_k (int k, vector < Query >& op) {for (int i = 0; I <= N1; + i) {
P[i] = i;
Val[i] = PII (Ridx[i], i);
G[i].clear ();
for (int o = 0; o < op.size (); + + O) {Query x = Op[o];
ANS[X.IDX] = PII (MAXN, MAXN);
for (int i = x.x I <= x.y + + i) {int L = X.L <= I 0: (x.l-i-1)/k + 1; int r = X.R < I?
-1: (x.r-i)/k;
if (L > R) continue;
L = L * k + i;
R = R * k + i;
G[l].push_back (PII (R, X.idx)); (int i = n1 i >= 0;--i) {for (int j = 0;J < G[i].size ();
+ + j) {int x = g[i][j].first, idx = G[i][j].second;
F (x);
ANS[IDX] = min (Ans[idx], val[x]);
} P[i] = i-k;
} inline void Solve () {build ();
Build_big_k ();
Query x;
int m, K;
scanf ("%d", &m);
for (int i = 0; i < SQR + i) small[i].clear (); for (int i = 1; I <= m + + i) {scanf ("%d%d%d%d%d", &X.L, &X.R, &k, &x.x, &x.y)
;
X.idx = i;
if (K < SQR) small[k].push_back (x);
Else Calc_big_k (k, x);
for (int i = 1; i < SQR + i) calc_small_k (i, small[i]); for (int i = 1; I <= m + + i) printf ("%d%c", Ans[i].first = = Maxn? -1:ans[i].second, I < m?
': ' \ n ');
int main () {while (~scanf ("%s%s", S1, S2)) solve ();
return 0; }