照着金策讲稿做。
Code
1 /**
2 * luogu
3 * Problem#P4482
4 * Accepted
5 * Time: 8264ms
6 * Memory: 37924k
7 */
8 #include <bits/stdc++.h>
9 using namespace std;
10 typedef bool boolean;
11
12 template <typename T>
13 void pfill(T* pst, const T* ped, T val) {
14 for ( ; pst != ped; *(pst++) = val);
15 }
16
17 const int N = 2e5 + 5;
18 const int bzmax = 19;
19 const signed int inf = (signed) (~0u >> 2);
20
21 typedef class SparseTable {
22 public:
23 int n;
24 int *ar;
25 int log2[N];
26 int f[N][bzmax];
27
28 SparseTable() { }
29
30 void init(int n, int* ar) {
31 this->n = n;
32 this->ar = ar;
33 log2[1] = 0;
34 for (int i = 2; i <= n; i++)
35 log2[i] = log2[i >> 1] + 1;
36 for (int i = 0; i < n; i++)
37 f[i][0] = ar[i];
38 for (int j = 1; j < bzmax; j++)
39 for (int i = 0; i + (1 << j) - 1 < n; i++)
40 f[i][j] = min(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
41 }
42
43 int query(int l, int r) {
44 int d = log2[r - l + 1];
45 return min(f[l][d], f[r - (1 << d) + 1][d]);
46 }
47 } SparseTable;
48
49 typedef class Pair3 {
50 public:
51 int x, y, id;
52
53 Pair3() { }
54 Pair3(int x, int y, int id):x(x), y(y), id(id) { }
55 } Pair3;
56
57 typedef class SuffixArray {
58 protected:
59 Pair3 T1[N], T2[N];
60 int cnt[N];
61
62 public:
63 int n;
64 char *str;
65 int sa[N], rk[N], hei[N];
66 SparseTable st;
67
68 void set(int n, char* str) {
69 this->n = n;
70 this->str = str;
71 memset(sa, 0, sizeof(sa));
72 memset(rk, 0, sizeof(rk));
73 memset(hei, 0, sizeof(hei));
74 }
75
76 void radix_sort(Pair3* x, Pair3* y) {
77 int m = max(n, 256);
78 memset(cnt, 0, sizeof(int) * m);
79 for (int i = 0; i < n; i++)
80 cnt[x[i].y]++;
81 for (int i = 1; i < m; i++)
82 cnt[i] += cnt[i - 1];
83 for (int i = 0; i < n; i++)
84 y[--cnt[x[i].y]] = x[i];
85
86 memset(cnt, 0, sizeof(int) * m);
87 for (int i = 0; i < n; i++)
88 cnt[y[i].x]++;
89 for (int i = 1; i < m; i++)
90 cnt[i] += cnt[i - 1];
91 for (int i = n - 1; ~i; i--)
92 x[--cnt[y[i].x]] = y[i];
93 }
94
95 void build() {
96 for (int i = 0; i < n; i++)
97 rk[i] = str[i];
98 for (int k = 1; k <= n; k <<= 1) {
99 for (int i = 0; i + k < n; i++)
100 T1[i] = Pair3(rk[i], rk[i + k], i);
101 for (int i = n - k; i < n; i++)
102 T1[i] = Pair3(rk[i], 0, i);
103 radix_sort(T1, T2);
104 int diff = 1;
105 rk[T1[0].id] = 1;
106 for (int i = 1; i < n; i++)
107 rk[T1[i].id] = (T1[i].x == T1[i - 1].x && T1[i].y == T1[i - 1].y) ? (diff) : (++diff);
108 if (diff == n)
109 break;
110 }
111 for (int i = 0; i < n; i++)
112 sa[--rk[i]] = i;
113 }
114
115 void get_height() {
116 for (int i = 0, j, k = 0; i < n; i++, (k) ? (k--) : (0)) {
117 if (rk[i]) {
118 j = sa[rk[i] - 1];
119 while (i + k < n && j + k < n && str[i + k] == str[j + k]) k++;
120 hei[rk[i]] = k;
121 }
122 }
123 }
124
125 void init_st() {
126 st.init(n, hei);
127 }
128
129 int lcp(int x1, int x2) {
130 if (x1 == x2)
131 return n - x1 + 1;
132 x1 = rk[x1], x2 = rk[x2];
133 if (x1 > x2)
134 swap(x1, x2);
135 return st.query(x1 + 1, x2);
136 }
137
138 int compare(int l1, int r1, int l2, int r2) {
139 int len_lcp = lcp(l1, l2);
140 int len1 = r1 - l1 + 1, len2= r2 - l2 + 1;
141 if (len_lcp >= len1 && len_lcp >= len2)
142 return 0;
143 if (len_lcp < len1 && len_lcp < len2)
144 return (str[l1 + len_lcp] < str[l2 + len_lcp]) ? (-1) : (1);
145 return (len_lcp >= len1) ? (-1) : (1);
146 }
147
148 int query(int u, int v) { // u, v -> sa
149 if (u == v)
150 return n - sa[u];
151 return st.query(u + 1, v);
152 }
153
154 const int& operator [] (int p) {
155 return sa[p];
156 }
157
158 const int& operator () (int p) {
159 return hei[p];
160 }
161 } SuffixArray;
162
163 namespace IPM { // Internal Pattern Matching
164
165 typedef class MatchingData {
166 public:
167 int a0, a1;
168 int amount;
169
170 MatchingData() : amount(0) { }
171 explicit MatchingData(int a0) : a0(a0), a1(a0), amount(1) { }
172 MatchingData(int a0, int a1) : a0(a0), a1(a1), amount(1 + (a0 != a1)) { }
173 MatchingData(int a0, int a1, int amount) : a0(a0), a1(a1), amount(amount) { }
174 MatchingData(int* a, int amount) : amount(amount) {
175 if (amount == 0)
176 return;
177 if (amount == 1)
178 a0 = a1 = a[0];
179 else if (amount >= 2) {
180 a0 = a[0], a1 = a[1];
181 int d = a1 - a0;
182 for (int i = 2; i < amount; i++)
183 if (a[i] - a[i - 1] != d)
184 assert(false);
185 }
186 }
187
188 boolean included(int x) {
189 if (!amount)
190 return false;
191 boolean aflag = (x == a0 || x == a1);
192 if (amount <= 2 || aflag)
193 return aflag;
194 x -= a0;
195 int d = a1 - a0;
196 return (!(x % d) && (x / d >= 0 && x / d < amount));
197 }
198
199 int indexOf(int x) {
200 if (!included(x))
201 return -1;
202 return (x - a0) / (a1 - a0);
203 }
204
205 int last() {
206 return value(amount - 1);
207 }
208
209 int value(int n) {
210 return a0 + (a1 - a0) * n;
211 }
212
213 int dif() {
214 return a1 - a0;
215 }
216
217 MatchingData operator - () {
218 return MatchingData(-a0, -a1, amount);
219 }
220
221 MatchingData operator + (int d) {
222 return MatchingData(a0 + d, a1 + d, amount);
223 }
224
225 MatchingData operator - (int d) {
226 return MatchingData(a0 - d, a1 - d, amount);
227 }
228
229 MatchingData operator ~ () {
230 if (amount <= 1)
231 return *this;
232 int _a0 = value(amount - 1);
233 int _a1 = value(amount - 2);
234 return MatchingData(_a0, _a1, amount);
235 }
236
237 MatchingData operator & (MatchingData b) {
238 static int tmp[6];
239 if (!amount || !b.amount)
240 return MatchingData();
241 if (amount < 3) {
242 int tp = 0;
243 for (int i = 0, x = a0, d = a1 - a0; i < amount; i++, x += d) {
244 if (b.included(x)) {
245 tmp[tp++] = x;
246 }
247 }
248 return MatchingData(tmp, tp);
249 }
250 if (b.amount < 3) {
251 int tp = 0;
252 for (int i = 0, x = b.a0, d = b.a1 - b.a0; i < b.amount; i++, x += d) {
253 if (included(x)) {
254 tmp[tp++] = x;
255 }
256 }
257 return MatchingData(tmp, tp);
258 }
259 int d = a1 - a0;
260 assert(d == b.a1 - b.a0);
261 int l = indexOf(b.a0), r = l + b.amount;
262 if (l == -1)
263 return MatchingData();
264 l = max(l, 0);
265 r = min(amount, r);
266 if (l >= r)
267 return MatchingData();
268 return MatchingData(value(l), value(l + 1), r - l);
269 }
270 } MatchingData;
271
272 int n;
273 char* str;
274 //int *log2;
275 SuffixArray sa;
276 int f[bzmax][N];
277
278 inline void init(char* str, int _n) {
279 // log2 = new int[(n + 1)];
280 // log2[0] = -1;
281 // for (int i = 1; i <= n; i++)
282 // log2[i] = log2[i >> 1] + 1;
283 n = _n;
284 sa.set(n, str);
285 sa.build();
286 sa.get_height();
287 sa.init_st();
288 for (int k = 0; (1 << k) <= n; k++) {
289 int* F = f[k], len = (1 << k);
290 for (int i = 0; i + len <= n; i++)
291 F[i] = i;
292 sort(F, F + (n - len) + 1, [&] (const int& x, const int& y) {
293 int rt = sa.compare(x, x + len - 1, y, y + len - 1);
294 if (!rt)
295 return x < y;
296 return rt == -1;
297 }); // it can be replace by radix sort
298 }
299 }
300
301 pair<int, int> getRange(int s, int k) {
302 int len = 1 << k, l = 0, r = n - len, mid;
303 int* F = f[k], L, R;
304 while (l <= r) {
305 mid = (l + r) >> 1;
306 if (sa.compare(s, s + len - 1, F[mid], F[mid] + len - 1) == 1)
307 l = mid + 1;
308 else
309 r = mid - 1;
310 }
311 L = r + 1;
312 l = 0, r = n - len;
313 while (l <= r) {
314 mid = (l + r) >> 1;
315 if (sa.compare(s, s + len - 1, F[mid], F[mid] + len - 1) >= 0)
316 l = mid + 1;
317 else
318 r = mid - 1;
319 }
320 R = l - 1;
321 return pair<int, int>(L, R);
322 }
323
324 int succ(int s, int k, int i, int L, int R) { // pos >= i
325 int len = 1 << k, l = 0, r = n - len;
326 int mid;
327 int *F = f[k];
328 if (L > R)
329 return inf;
330 l = L, r = R;
331 while (l <= r) {
332 mid = (l + r) >> 1;
333 if (F[mid] >= i)
334 r = mid - 1;
335 else
336 l = mid + 1;
337 }
338 if (r == R)
339 return inf;
340 return F[r + 1];
341 }
342
343 int pred(int s, int k, int i) { //<= i
344 int len = 1 << k, l = 0, r = n - len;
345 int L, R, mid;
346 int *F = f[k];
347 while (l <= r) {
348 mid = (l + r) >> 1;
349 if (sa.compare(s, s + len - 1, F[mid], F[mid] + len - 1) == 1)
350 l = mid + 1;
351 else
352 r = mid - 1;
353 }
354 L = r + 1;
355 l = 0, r = n - len;
356 while (l <= r) {
357 mid = (l + r) >> 1;
358 if (sa.compare(s, s + len - 1, F[mid], F[mid] + len - 1) >= 0)
359 l = mid + 1;
360 else
361 r = mid - 1;
362 }
363 R = l - 1;
364 if (L > R)
365 return -1;
366 l = L, r = R;
367 while (l <= r) {
368 mid = (l + r) >> 1;
369 if (F[mid] <= i)
370 l = mid + 1;
371 else
372 r = mid - 1;
373 }
374 if (l == L)
375 return -1;
376 return F[l - 1];
377 }
378
379 // rt - lt + 1 = 2 ^ k
380 MatchingData query(int ls, int rs, int lt, int k) {
381 int len = 1 << k;
382 pair<int, int> range = getRange(lt, k);
383 int a0 = succ(lt, k, ls, range.first, range.second);
384 if (a0 + len - 1 > rs)
385 return MatchingData();
386 int a1 = succ(lt, k, a0 + 1, range.first, range.second);
387 if (a1 + len - 1 > rs)
388 return MatchingData(a0);
389 int an = pred(lt, k, rs - len + 1);
390 assert(an >= ls);
391 MatchingData rt (a0, a1);
392 rt.amount = N;
393 rt.amount = rt.indexOf(an) + 1;
394 return rt;
395 }
396
397 }
398
399 using IPM :: MatchingData;
400
401 int n, m;
402 char str[N];
403
404 inline void init() {
405 scanf("%s", str);
406 n = strlen(str);
407 IPM :: init(str, n);
408 }
409
410 int query(int l, int r) {
411 int t = 0, half_len = (r - l + 2) >> 1;
412 while ((1 << t) < half_len)
413 t++;
414 for (int i = t; ~i; i--) {
415 int len = min(r - l, 1 << (i + 1)), hlen = (1 << i);
416 MatchingData md_l = IPM :: query(l, l + len - 1, r - hlen + 1, i);
417 MatchingData md_r = IPM :: query(r - len + 1, r, l, i);
418 md_l = md_l - l + hlen;
419 md_r = -(~md_r) + (r + 1);
420 md_l = md_l & md_r;
421 if (md_l.amount)
422 return md_l.last();
423 }
424 return (str[l] == str[r] && l < r);
425 }
426
427 inline void solve() {
428 scanf("%d", &m);
429 int l, r;
430 while (m--) {
431 scanf("%d%d", &l, &r);
432 printf("%d\n", query(--l, --r));
433 }
434 }
435
436 int main() {
437 // freopen("border.in", "r", stdin);
438 // freopen("border.out", "w", stdout);
439 init();
440 solve();
441 return 0;
442 }
来源:https://www.cnblogs.com/yyf0309/p/10232477.html