| 33 | } |
| 34 | } |
| 35 | struct SuffixArray { |
| 36 | int n; |
| 37 | vector<int> s; |
| 38 | vector<int> sa, rank, lcp; |
| 39 | static const int LG = 18; |
| 40 | vector<vector<int>> t; |
| 41 | vector<int> lg; |
| 42 | SuffixArray() {} |
| 43 | SuffixArray(vector<int> _s) { |
| 44 | n = _s.size(); |
| 45 | s = _s; |
| 46 | for (int i = 0; i < n; i++) str[i] = s[i]; //for integers, each element should be positive |
| 47 | str[n] = 0; |
| 48 | suffix_array_DA(n + 1, kinds); |
| 49 | for (int i = 1; i <= n; i++) sa.push_back(suf[i]); |
| 50 | rank.resize(n); |
| 51 | for (int i = 0; i < n; i++) rank[sa[i]] = i; |
| 52 | costruct_lcp(); |
| 53 | prec(); |
| 54 | build(); |
| 55 | } |
| 56 | void costruct_lcp() { |
| 57 | int k = 0; |
| 58 | lcp.resize(n - 1, 0); |
| 59 | for (int i = 0; i < n; i++) { |
| 60 | if (rank[i] == n - 1) { |
| 61 | k = 0; |
| 62 | continue; |
| 63 | } |
| 64 | int j = sa[rank[i] + 1]; |
| 65 | while (i + k < n && j + k < n && s[i + k] == s[j + k]) k++; |
| 66 | lcp[rank[i]] = k; |
| 67 | if (k) k--; |
| 68 | } |
| 69 | } |
| 70 | void prec() { |
| 71 | lg.resize(n, 0); |
| 72 | for (int i = 2; i < n; i++) lg[i] = lg[i / 2] + 1; |
| 73 | } |
| 74 | void build() { |
| 75 | int sz = n - 1; |
| 76 | t.resize(sz); |
| 77 | for (int i = 0; i < sz; i++) { |
| 78 | t[i].resize(LG); |
| 79 | t[i][0] = lcp[i]; |
| 80 | } |
| 81 | for (int k = 1; k < LG; ++k) { |
| 82 | for (int i = 0; i + (1 << k) - 1 < sz; ++i) { |
| 83 | t[i][k] = min(t[i][k - 1], t[i + (1 << (k - 1))][k - 1]); |
| 84 | } |
| 85 | } |
| 86 | } |
| 87 | int query(int l, int r) { // minimum of lcp[l], ..., lcp[r] |
| 88 | int k = lg[r - l + 1]; |
| 89 | return min(t[l][k], t[r - (1 << k) + 1][k]); |
| 90 | } |
| 91 | int get_lcp(int i, int j) { // lcp of suffix starting from i and j |
| 92 | if (i == j) return n - i; |
no outgoing calls
no test coverage detected