后缀数组
Posted __AiR_H
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了后缀数组相关的知识,希望对你有一定的参考价值。
1 FZU 2267 The Bigger the Better
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 #include <queue> 7 #include <vector> 8 #include <stack> 9 #include <map> 10 #include <set> 11 #include <cmath> 12 #include <cctype> 13 #include <ctime> 14 15 using namespace std; 16 17 #define REP(i, n) for (int i = 0; i < (n); ++i) 18 #define eps 1e-9 19 #define rank rank_t 20 21 typedef long long ll; 22 typedef pair<int, int> pii; 23 24 const int INF = 0x7fffffff; 25 const int maxn = 2e5 + 10; 26 int sa[maxn], cnt[maxn], t1[maxn], t2[maxn], rank[maxn], height[maxn]; 27 int a[maxn / 2], b[maxn / 2], s[maxn], ans[maxn], Min[maxn][20], key[maxn]; 28 29 void build_sa(int Max, int len_t) { 30 int i, p, *x = t1, *y = t2; 31 for (i = 0; i < Max; ++i) { cnt[i] = 0; } 32 for (i = 0; i < len_t; ++i) { ++cnt[x[i] = s[i]]; } 33 for (i = 1; i < Max; ++i) { cnt[i] += cnt[i - 1]; } 34 for (i = len_t - 1; i >= 0; --i) { sa[--cnt[x[i]]] = i; } 35 for (int k = 1; k <= len_t; k <<= 1) { 36 p = 0; 37 for (i = len_t - k; i < len_t; ++i) { y[p++] = i; } 38 for (i = 0; i < len_t; ++i) { 39 if (sa[i] >= k) { y[p++] = sa[i] - k; } 40 } 41 for (i = 0; i < Max; ++i) { cnt[i] = 0; } 42 for (i = 0; i < len_t; ++i) { ++cnt[x[y[i]]]; } 43 for (i = 1; i < Max; ++i) { cnt[i] += cnt[i - 1]; } 44 for (i = len_t - 1; i >= 0; --i) { sa[--cnt[x[y[i]]]] = y[i]; } 45 swap(x, y); p = 1; x[sa[0]] = 0; 46 for (i = 1; i < len_t; ++i) { 47 if (y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + k] == y[sa[i] + k]) { 48 x[sa[i]] = p - 1; 49 } else { x[sa[i]] = p++; } 50 } 51 if (p >= len_t) { break; } Max = p; 52 } 53 } 54 void get_height(int len) { 55 int i, j, k = 0; 56 for (i = 0; i <= len; ++i) { rank[sa[i]] = i; } 57 for (i = 0; i < len; ++i) { 58 if (k) { --k; } j = sa[rank[i] - 1]; 59 while (s[i + k] == s[j + k]) { ++k; } 60 height[rank[i]] = k; 61 } 62 } 63 void init(int n) { 64 for (int i = 1; i <= n; ++i) { Min[i][0] = height[i]; } 65 for (int j = 1; (1 << j) <= n; ++j) { 66 for (int i = 1; i + (1 << j) - 1 <= n; ++i) { 67 Min[i][j] = min(Min[i][j - 1], Min[i + (1 << (j - 1))][j - 1]); 68 } 69 } 70 } 71 inline int rmq(int l, int r) { 72 int k = key[r - l + 1]; 73 return min(Min[l][k], Min[r - (1 << k) + 1][k]); 74 } 75 void print(int l, int len) { 76 for (int i = l; i < len; ++i) { printf("%d ", s[i]); } printf("\n"); 77 } 78 79 int main() { 80 #ifdef __AiR_H 81 freopen("in.txt", "r", stdin); 82 // freopen("out.txt", "w", stdout); 83 #endif // __AiR_H 84 int T, n, m, Case = 0, len, ans_cnt; 85 for (int i = 1; i < maxn; ++i) { 86 while ((1 << (key[i] + 1)) <= i) { ++key[i]; } 87 } 88 scanf("%d", &T); 89 while (T--) { 90 scanf("%d %d", &n, &m); len = ans_cnt = 0; 91 for (int i = 0; i < n; ++i) { scanf("%d", &a[i]); s[len++] = a[i]; } 92 s[len++] = 10; 93 for (int i = 0; i < m; ++i) { scanf("%d", &b[i]); s[len++] = b[i]; } 94 s[len] = 0; build_sa(11, len + 1); get_height(len); init(len); 95 int t_1, t_2, t_3; 96 for (int i = 0, j = 0; ; ) { 97 if (i == n) { 98 for (; j < m; ++j) { ans[ans_cnt++] = b[j]; } break; 99 } 100 if (j == m) { 101 for (; i < n; ++i) { ans[ans_cnt++] = a[i]; } break; 102 } 103 if (a[i] > b[j]) { ans[ans_cnt++] = a[i]; ++i; continue; } 104 if (b[j] > a[i]) { ans[ans_cnt++] = b[j]; ++j; continue; } 105 t_1 = rank[i]; t_2 = rank[n + j + 1]; 106 if (t_1 > t_2) { swap(t_1, t_2); } t_3 = rmq(t_1 + 1, t_2); 107 if (i + t_3 >= n) { ans[ans_cnt++] = b[j]; ++j; continue; } 108 if (j + t_3 >= m) { ans[ans_cnt++] = a[i]; ++i; continue; } 109 if (a[i + t_3] > b[j + t_3]) { ans[ans_cnt++] = a[i]; ++i; continue; } 110 ans[ans_cnt++] = b[j]; ++j; 111 } 112 printf("Case %d: ", ++Case); 113 for (int i = 0; i < ans_cnt; ++i) { printf("%d", ans[i]); } 114 printf("\n"); 115 } 116 #ifdef __AiR_H 117 printf("Time used = %.2fs\n", (double)clock() / CLOCKS_PER_SEC); 118 #endif // __AiR_H 119 return 0; 120 }
以上是关于后缀数组的主要内容,如果未能解决你的问题,请参考以下文章