Advertisement
rayated

fully working suffix array template

Nov 8th, 2024
79
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.58 KB | Source Code | 0 0
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. struct SuffixArray
  5. {
  6.   int n, LG;
  7.   string s;
  8.   vector<int> sa, rank, lcp;
  9.   vector<vector<int>> t;
  10.   vector<int> lg;
  11.   SuffixArray() {}
  12.   SuffixArray(string _s)
  13.   {
  14.     n = _s.size();
  15.     LG = log2(n) + 2;
  16.     s = _s;
  17.     sa = build_suffix_array(s);
  18.     rank.resize(n);
  19.     for (int i = 0; i < n; i++)
  20.       rank[sa[i]] = i;
  21.     construct_lcp();
  22.     build();
  23.   }
  24.   vector<int> build_suffix_array(string s)
  25.   { // suffix array of s
  26.     s += '$';
  27.     int n = s.size();
  28.     vector<int> p(n), c(n);
  29.     vector<int> pnew(n), cnew(n), cnt(max(256, n));
  30.     for (char ch : s)
  31.       cnt[ch]++;
  32.     for (int i = 1; i < 256; i++)
  33.       cnt[i] += cnt[i - 1];
  34.     for (int i = 0; i < n; i++)
  35.       p[--cnt[s[i]]] = i;
  36.     for (int i = 1; i < n; i++)
  37.       c[p[i]] = c[p[i - 1]] + (s[p[i]] != s[p[i - 1]]);
  38.     for (int k = 0; (1 << k) < n; k++)
  39.     {
  40.       for (int i = 0; i < n; i++)
  41.         p[i] = (p[i] - (1 << k) + n) % n;
  42.       cnt.assign(n, 0);
  43.       for (auto x : c)
  44.         cnt[x]++;
  45.       for (int i = 1; i < n; i++)
  46.         cnt[i] += cnt[i - 1];
  47.       for (int i = n - 1; i >= 0; i--)
  48.         pnew[--cnt[c[p[i]]]] = p[i];
  49.       p.swap(pnew);
  50.       cnew[p[0]] = 0;
  51.       for (int i = 1; i < n; i++)
  52.       {
  53.         pair<int, int> prev = {c[p[i - 1]], c[(p[i - 1] + (1 << k)) % n]};
  54.         pair<int, int> now = {c[p[i]], c[(p[i] + (1 << k)) % n]};
  55.         cnew[p[i]] = cnew[p[i - 1]] + (now != prev);
  56.       }
  57.       c = cnew;
  58.     }
  59.     p.erase(p.begin());
  60.     return p;
  61.   }
  62.   void construct_lcp()
  63.   { // lcp of sa[i] and sa[i + 1]
  64.     int k = 0;
  65.     lcp.resize(n - 1, 0);
  66.     for (int i = 0; i < n; i++)
  67.     {
  68.       if (rank[i] == n - 1)
  69.       {
  70.         k = 0;
  71.         continue;
  72.       }
  73.       int j = sa[rank[i] + 1];
  74.       while (i + k < n && j + k < n && s[i + k] == s[j + k])
  75.         k++;
  76.       lcp[rank[i]] = k;
  77.       if (k)
  78.         k--;
  79.     }
  80.   }
  81.   void build()
  82.   { // sparse table of lcp
  83.     lg.resize(n + 1);
  84.     for (int i = 2; i <= n; i++)
  85.       lg[i] = lg[i >> 1] + 1;
  86.  
  87.     int sz = n - 1;
  88.     t.resize(sz);
  89.  
  90.     for (int i = 0; i < sz; i++)
  91.     {
  92.       t[i].resize(LG);
  93.       t[i][0] = lcp[i];
  94.     }
  95.  
  96.     for (int k = 1; k < LG; ++k)
  97.       for (int i = 0; i + (1 << k) - 1 < sz; ++i)
  98.         t[i][k] = min(t[i][k - 1], t[i + (1 << (k - 1))][k - 1]);
  99.   }
  100.   int query(int l, int r)
  101.   { // minimum of lcp[l], ..., lcp[r]
  102.     int k = lg[r - l + 1];
  103.     return min(t[l][k], t[r - (1 << k) + 1][k]);
  104.   }
  105.   int get_lcp(int i, int j)
  106.   { // lcp of suffix starting from i and j
  107.     if (i == j)
  108.       return n - i;
  109.     int l = rank[i], r = rank[j];
  110.     if (l > r)
  111.       swap(l, r);
  112.     return query(l, r - 1);
  113.   }
  114.   int lower_bound(string &t)
  115.   { // first occurrence of t in sa
  116.     int l = 0, r = n - 1, k = t.size(), ans = n;
  117.     while (l <= r)
  118.     {
  119.       int mid = l + (r - l) / 2;
  120.       if (s.substr(sa[mid], min(n - sa[mid], k)) >= t)
  121.         ans = mid, r = mid - 1;
  122.       else
  123.         l = mid + 1;
  124.     }
  125.     return ans;
  126.   }
  127.   int upper_bound(string &t)
  128.   { // last occurrence of t in sa
  129.     int l = 0, r = n - 1, k = t.size(), ans = n;
  130.     while (l <= r)
  131.     {
  132.       int mid = l + (r - l) / 2;
  133.       if (s.substr(sa[mid], min(n - sa[mid], k)) > t)
  134.         ans = mid, r = mid - 1;
  135.       else
  136.         l = mid + 1;
  137.     }
  138.     return ans;
  139.   }
  140. };
  141.  
  142. int main()
  143. {
  144.   string s;
  145.   cin >> s;
  146.   SuffixArray sa(s);
  147.  
  148.   for (int i = 0; i < s.size(); i++)
  149.     cout << sa.sa[i] << " ";
  150.   cout << "\n";
  151.  
  152.   for (int i = 0; i < s.size() - 1; i++)
  153.     cout << sa.lcp[i] << " ";
  154. }
  155.  
Tags: suffix array
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement