后缀数组

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 }
View Code

 

以上是关于后缀数组的主要内容,如果未能解决你的问题,请参考以下文章

VSCode自定义代码片段—— 数组的响应式方法

VSCode自定义代码片段10—— 数组的响应式方法

Sublime Text3自定义代码片段

后缀数组代码详解

●后缀数组○十三个例题

初学后缀数组记录(然而并不是很会。。&&很水。。)