|
11 | 11 | //! @time O(n * log^2(n)) |
12 | 12 | //! @space O(n) |
13 | 13 | auto sa_short(const auto& s) { |
14 | | - const int K = 4; |
15 | | - int n = sz(s); |
| 14 | + const int n = sz(s), K = 4; |
16 | 15 | vi sa(n), sa_inv(all(s)), lcp(n - 1); |
17 | 16 | iota(all(sa), 0); |
18 | 17 | for (int j = 1; j <= n; j *= K) { |
19 | | - vi x(sa_inv); |
20 | | - auto proj = [&](int i) { |
| 18 | + vi x(sa_inv), y(lcp); |
| 19 | + auto f = [&](int i) { |
21 | 20 | array<int, K> res; |
22 | 21 | rep (k, 0, K) |
23 | 22 | res[k] = i + j * k < n ? x[i + j * k] : -1; |
24 | 23 | return res; |
25 | | - //return pair(x[i], i + j < n ? x[i + j] : -1); |
26 | 24 | }; |
27 | | - ranges::sort(sa, {}, proj); |
| 25 | + ranges::sort(sa, {}, f); |
28 | 26 | sa_inv[sa[0]] = 0; |
29 | | - rep(i, 1, n) sa_inv[sa[i]] = |
30 | | - sa_inv[sa[i - 1]] + (proj(sa[i - 1]) != proj(sa[i])); |
31 | | - } |
32 | | - int sz = 0; |
33 | | - rep(i, 0, n) { |
34 | | - if (sz > 0) sz--; |
35 | | - if (sa_inv[i] == 0) continue; |
36 | | - for (int j = sa[sa_inv[i] - 1]; |
37 | | - max(i, j) + sz < n && s[i + sz] == s[j + sz];) |
38 | | - sz++; |
39 | | - lcp[sa_inv[i] - 1] = sz; |
| 27 | + rep(i, 0, n - 1) { |
| 28 | + sa_inv[sa[i + 1]] = sa_inv[sa[i]]; |
| 29 | + if (f(sa[i + 1]) != f(sa[i])) { |
| 30 | + sa_inv[sa[i]]++; |
| 31 | + rep (k, 0, K) { |
| 32 | + if (f(sa[i + 1])[k] != f(sa[i])[k]) { |
| 33 | + lcp[i] = j * k + (i + j * k < n ? y[i + j * k] : 0); |
| 34 | + } |
| 35 | + } |
| 36 | + } else { |
| 37 | + lcp[i] = j * K; |
| 38 | + } |
| 39 | + } |
40 | 40 | } |
41 | 41 | return tuple{sa, sa_inv, lcp}; |
42 | 42 | } |
0 commit comments