Mlxa

TEAMBOOK суффиксный массив

Nov 1st, 2019
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.27 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2. using long_type = long long;
  3. #define long long_type
  4. using namespace std;
  5.  
  6. const int max_n     = 3e5;
  7. const int alphabet  = 101;
  8. int n, arr[max_n], suf[max_n], eq[max_n], temp[max_n], inv[max_n], lcp[max_n];
  9. vector<int> bucket[max_n];
  10.  
  11. int mod(int i) {
  12.     i += n;
  13.     return i % n;
  14. }
  15.  
  16. void check(int i, int j) {
  17.     for (int k = 0; ; ++k) {
  18.         if (arr[i + k] != arr[j + k]) {
  19.             assert(arr[i + k] < arr[j + k]);
  20.             return;
  21.         }
  22.     }
  23. }
  24.  
  25. void solve() {
  26.     assert(n <= 50000);
  27.     for (int i = 0; i < n; ++i) {
  28.         cin >> arr[i];
  29.         ++arr[i];
  30.         arr[i + n] = arr[i];
  31.     }
  32.     arr[2 * n] = 0;
  33.     n = 2 * n + 1;
  34.     for (int i = 0; i < n; ++i) {
  35.         eq[i] = arr[i];
  36.     }
  37.     iota(suf, suf + n, 0);
  38.     sort(suf, suf + n, [&](int i, int j) {
  39.         return arr[i] < arr[j];
  40.     });
  41.     for (int len = 1; len < n; len *= 2) {
  42.         for (int i = 0; i < n; ++i) {
  43.             int j = mod(suf[i] - len);
  44.             bucket[eq[j]].push_back(j);
  45.         }
  46.         int ptr = 0;
  47.         for (int num = 0; num < n || num <= alphabet; ++num) {
  48.             for (int i : bucket[num]) {
  49.                 suf[ptr++] = i;
  50.             }
  51.             bucket[num].clear();
  52.         }
  53.         temp[suf[0]] = 0;
  54.         for (int i = 1; i < n; ++i) {
  55.             temp[suf[i]] = temp[suf[i - 1]];
  56.             int a = eq[suf[i - 1]], b = eq[mod(suf[i - 1] + len)];
  57.             int c = eq[suf[i]],     d = eq[mod(suf[i] + len)];
  58.             if (a != c || b != d) {
  59.                 ++temp[suf[i]];
  60.             }
  61.         }
  62.         copy(temp, temp + n, eq);
  63.     }
  64.     for (int i = 0; i < n; ++i) {
  65.         //~ cout << suf[i] << " ";
  66.         inv[suf[i]] = i;
  67.     }
  68.     //~ cout << endl;
  69.     int k = 0;
  70.     long answer = 0;
  71.     for (int i = 0; i < n; ++i) {
  72.         if (inv[i] == n - 1) {
  73.             k = 0;
  74.             continue;
  75.         }
  76.         k = max(0, k - 1);
  77.         int j = suf[inv[i] + 1];
  78.         while (k < n && arr[i + k] == arr[j + k]) {
  79.             ++k;
  80.         }
  81.         lcp[i] = k;
  82.     }
  83.     int cur = n;
  84.     bool was = false;
  85.     for (int i = 0; i < n; ++i) {
  86.         if (suf[i] < n / 2) {
  87.             if (was) {
  88.                 answer += min(cur, n / 2);
  89.                 //cout << min(cur, n / 2) << " ";
  90.             }
  91.             cur = lcp[suf[i]];
  92.             was = true;
  93.         } else {
  94.             cur = min(cur, lcp[suf[i]]);
  95.         }
  96.     }
  97.     cout << answer << "\n";
  98. }
  99.  
  100. int main() {
  101. #ifdef LC
  102.     assert(freopen("input.txt", "r", stdin));
  103. #else
  104.     assert(freopen("towers.in", "r", stdin));
  105.     assert(freopen("towers.out", "w", stdout));
  106. #endif
  107.     ios::sync_with_stdio(0);
  108.     cin.tie(0);
  109.     while (cin >> n && n) {
  110.         solve();
  111.     }
  112.     return 0;
  113. }
Add Comment
Please, Sign In to add comment