leoanjos

Protein Manufacturing

Jun 20th, 2023
895
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.42 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. #define llong long long int
  6.  
  7. const int LOG = 20;
  8.  
  9. struct SparseTable {
  10. private:
  11.     int n;
  12.     vector<vector<int>> table;
  13.  
  14. public:
  15.     SparseTable() {}
  16.     SparseTable(vector<int> &a) {
  17.         n = a.size();
  18.         table.assign(LOG, vector<int>(n));
  19.  
  20.         for (int i = 0; i < n; i++)
  21.             table[0][i] = a[i];
  22.  
  23.         for (int i = 1; i < LOG; i++) {
  24.             int jump = 1 << (i - 1);
  25.             for (int j = 0; j < n; j++) {
  26.                 table[i][j] = table[i - 1][j];
  27.                 if (j + jump < n)
  28.                     table[i][j] = min(table[i][j], table[i - 1][j + jump]);
  29.             }
  30.         }
  31.     }
  32.  
  33.     int get_min(int l, int r) {
  34.         int idx = __lg(r - l + 1), jump = 1 << idx;
  35.         return min(table[idx][l], table[idx][r - jump + 1]);
  36.     }
  37. };
  38.  
  39. struct SuffixArray {
  40. private:
  41.     int n, m;
  42.     string text;
  43.     vector<int> pstart;
  44.     vector<int> rank, suffixes, lcp;
  45.     SparseTable table;
  46.     vector<int> ps;
  47.  
  48. public:
  49.     SuffixArray(string text): text(text), m(text.size()) {}
  50.  
  51.     void add_pattern(string pattern) {
  52.         n = text.size();
  53.         text += "|" + pattern;
  54.         pstart.push_back(n + 1);
  55.     }
  56.  
  57.     void build() {
  58.         text += '$';
  59.         n = text.size();
  60.  
  61.         vector<pair<char, int>> letters(n);
  62.         for (int i = 0; i < n; i++)
  63.             letters[i] = make_pair(text[i], i);
  64.  
  65.         sort(letters.begin(), letters.end());
  66.  
  67.         int idx = 0;
  68.         rank.resize(n);
  69.         suffixes.resize(n);
  70.  
  71.         for (int i = 0; i < n; i++) {
  72.             if (i && letters[i].first > letters[i - 1].first) idx++;
  73.             suffixes[i] = letters[i].second;
  74.             rank[suffixes[i]] = idx;
  75.         }
  76.  
  77.         for (int p = 1; p < 2 * n; p <<= 1) {
  78.             idx = -1;
  79.             int end = 0;
  80.             vector<int> nrank(n);
  81.  
  82.             while (end < n) {
  83.                 int begin = end++;
  84.                 while (end < n && rank[suffixes[end]] == rank[suffixes[end - 1]]) end++;
  85.  
  86.                 vector<pair<int, int>> order(end - begin);
  87.                 for (int i = begin; i < end; i++)
  88.                     order[i - begin] = make_pair(rank[(suffixes[i] + p) % n], suffixes[i]);
  89.  
  90.                 sort(order.begin(), order.end());
  91.                 for (int i = begin; i < end; i++) {
  92.                     if (i == begin || order[i - begin].first > order[i - begin - 1].first) idx++;
  93.                     suffixes[i] = order[i - begin].second;
  94.                     nrank[suffixes[i]] = idx;
  95.                 }
  96.             }
  97.  
  98.             rank = nrank;
  99.         }
  100.  
  101.         for (int i = 1; i < n; i++)
  102.             assert(rank[suffixes[i]] > rank[suffixes[i - 1]]);
  103.  
  104.         ps.assign(n, 0);
  105.         ps[0] = suffixes[0] < m;
  106.  
  107.         for (int i = 1; i < n; i++)
  108.             ps[i] = ps[i - 1] + (suffixes[i] < m);
  109.  
  110.         build_lcp();
  111.     }
  112.  
  113.     int matches(int l, int r, int pattern = 0) {
  114.         int sz = r - l + 1;
  115.         int idx = rank[pstart[pattern] + l];
  116.  
  117.         l = idx;
  118.         int lo = 1, hi = idx;
  119.  
  120.         while (lo <= hi) {
  121.             int mid = (lo + hi) / 2;
  122.             if (table.get_min(idx - mid, idx - 1) < sz) hi = mid - 1;
  123.             else lo = mid + 1, l = idx - mid;
  124.         }
  125.  
  126.         r = idx;
  127.         lo = 1; hi = n - idx - 1;
  128.  
  129.         while (lo <= hi) {
  130.             int mid = (lo + hi) / 2;
  131.             if (table.get_min(idx, idx + mid - 1) < sz) hi = mid - 1;
  132.             else lo = mid + 1, r = idx + mid;
  133.         }
  134.  
  135.         assert(l);
  136.         return ps[r] - ps[l - 1];
  137.     }
  138.  
  139. private:
  140.     void build_lcp() {
  141.         int pref = 0;
  142.         lcp.assign(n, 0);
  143.  
  144.         for (int i = 0; i < n; i++) {
  145.             if (rank[i] + 1 >= n) {
  146.                 pref = 0;
  147.                 continue;
  148.             }
  149.  
  150.             int nxt = suffixes[rank[i] + 1];
  151.             while (text[i + pref] == text[nxt + pref]) pref++;
  152.  
  153.             lcp[rank[i]] = pref;
  154.             if (pref) pref--;
  155.         }
  156.  
  157.         table = SparseTable(lcp);
  158.     }
  159. };
  160.  
  161. int main() {
  162.     ios_base::sync_with_stdio(false);
  163.     cin.tie(NULL);
  164.  
  165.     int N, M;
  166.     cin >> N >> M;
  167.  
  168.     string S; cin >> S;
  169.     SuffixArray sa(S);
  170.  
  171.     string T; cin >> T;
  172.     sa.add_pattern(T);
  173.  
  174.     sa.build();
  175.  
  176.     int Q; cin >> Q;
  177.     while (Q--) {
  178.         int A, B;
  179.         cin >> A >> B;
  180.  
  181.         int ans = sa.matches(A - 1, B - 1);
  182.         cout << ans << "\n";
  183.     }
  184. }
Advertisement
Add Comment
Please, Sign In to add comment