It is easy to understand. It provides a string with a maximum of 2000 and q queries. Each time you ask how many different strings are in the [l, r] interval.
(In order to unify the interpretation of this paper, the sa array value here is from 1 to n, but in the Code, the sa array value is from 0 to n-1 ).
Solution: In the suffix array paper, a similar question is used to find the number of different strings in a string. Ask how many different strings there are, that is, for each suffix, there are several prefixes different from those of other suffixes in all its prefixes. The solution is to add the suffixes one by one based on rank. Then, each time a suffix is added, n-sa [I] + 1 prefixes will be added, but in these prefixes, some of them have appeared before. The number that has appeared before is the length of the longest common prefix of I and all the suffixes added before. Obviously, it is the height [I]. The number of different strings that can be obtained each time is n-sa [I] + 1-height [I]. During the competition, [l, r] is used to construct a new string and directly process da again, but it times out (it is said that someone has passed, incredible ). After the game, we made improvements. We first processed the entire string through da (basic processing of Suffix Arrays) and processed the rank, sa, and height arrays. Q: I have answered questions again and again. At the beginning, I thought of sorting the suffixes of [l, r] based on their rank, then, the rank value is used to solve the problem similar to the paper, and the problem still times out later. In fact, we do not need to sort it, because we have already processed the rank array and sa array. We use a pos array to record the suffixes that appear between l and r. The initial value is-1, and the pos [I] indicates who is the suffix of I, which has the same meaning as sa, but here we only need the suffix between l and r, So we assign the-1 value to others. Then, the pos [I] =-1 is scanned from 1 to n. If pos [I] =-1, it indicates that the suffix of the ranking is not in the [l, r] range, then no processing is performed. Otherwise, it will be done in a way similar to the paper. But pay attention to one problem here. We can obtain different prefixes (that is, the substring to be obtained) for the added [l, r] suffix I) the number is n-sa [I] + 1-d, where d is not the height [I] above, because for height [I], it is possible that its length has exceeded r-sa [I] + 1 (this is the longest length that can be provided for the I suffix ). Therefore, d should be the suffix j for all the extensions added before I. Take max (min (lcp (j, I), min (r-j + 1, r-I + 1 ))). Of course we cannot enumerate j every time, but we only need to update this d every time.
# Include <stdio. h> # include <string. h> # include <algorithm> # include <stdlib. h> # define ll _ int64using namespace std; const int maxn = 1111111; ll f [maxn], g [maxn]; int wa [maxn], wb [maxn], wv [maxn], ws [maxn], pos [maxn]; struct suf {int sa [maxn], hei [maxn], rank [maxn]; int cmp (int * r, int I, int j, int l) {return r [I] = r [j] & r [I + l] = r [j + l];} void da (int * r, int n, int m) {int * X = wa, * y = wb, * t; int I, j, p; for (I = 0; I <m; I ++) ws [I] = 0; for (I = 0; I <n; I ++) ws [x [I] = r [I] ++; for (I = 1; I <m; I ++) ws [I] ++ = ws [I-1]; for (I = n-1; I> = 0; I --) sa [-- ws [x [I] = I; for (j = 1, p = 1; p <n; j * = 2, m = p) {for (p = 0, I = n-j; I <n; I ++) y [p ++] = I; for (I = 0; I <n; I ++) if (sa [I]> = j) y [p ++] = sa [I]- J; for (I = 0; I <m; I ++) ws [I] = 0; for (I = 0; I <n; I ++) ws [x [I] ++; for (I = 1; I <m; I ++) ws [I] + = ws [I-1]; for (I = n-1; I> = 0; I --) sa [-- ws [x [y [I] = y [I]; for (t = x, x = y, y = t, p = 1, x [sa [0] = 0, I = 1; I <n; I ++) x [sa [I] = cmp (y, sa [I-1], sa [I], j )? P-1: p ++;} int k = 0; for (I = 1; I <n; I ++) rank [sa [I] = I; // Here sa [0] does not need to be added with for (I = 0; I <n-1; hei [rank [I ++] = k) // same as above, rank [n-1] = 0 for (k? K --: 0, j = sa [rank [I]-1]; r [I + k] = r [j + k]; k ++ );}} arr; int s1 [maxn], dp [20] [2222]; void rmq (int n) {int I, j; f [0] = 1; for (I = 1; I <= 15; I ++) f [I] = f [I-1] * 2; g [0] =-1; for (I = 1; I <2222; I ++) g [I] = g [I> 1] + 1; for (I = 1; f [I] <= n; I ++) for (j = 1; j + f [I]-1 <= n; j ++) dp [I] [j] = min (dp [I-1] [j], dp [I-1] [j + f [I-1]);} int query (int l, Int r) {if (l = r) return dp [0] [l]; if (l> r) swap (l, r); int I, j, k; k = g [r-l + 1]; return min (dp [k] [l], dp [k] [r-f [k] + 1]);} char s [maxn]; int num [maxn]; int main () {int n, k, I, l, r; int cas; scanf ("% d ", & cas); while (cas --) {int q; scanf ("% s", s); int len = strlen (s); for (I = 0; I <len; I ++) s1 [I] = s [I]; s1 [len] = 0; arr. da (s1, len + 1,555); for (I = 1; I <= len; I ++) dp [0] [I] = arr. hei [I]; rmq (len); n = len; scanf ("% d", & q); while (q --) {scanf ("% d ", & l, & r); int ans = (r-l + 1) * (r-l + 2)/2; for (I = 0; I <= n; I ++) pos [I] =-1; for (I = l; I <= r; I ++) pos [arr. rank [I-1] = I-1; int last =-1, d = 0; for (I = 1; I <= n; I ++) {if (pos [I]! =-1) {if (last! =-1) {int t = query (arr. rank [last] + 1, arr. rank [pos [I]); d = min (d, t); d = max (d, min (t, r-last )); ans-= min (d, r-pos [I]);} last = pos [I];} printf ("% d \ n", ans );}}} /* 100baaba1003 4100hgtll1001 3100jghgtuklllsdd1003 5 */