Problem p02250 (C++) — buggy submission, verdict: Memory Limit Exceeded

#include <bits/stdc++.h>
using namespace std;

class suffix_array {
  const int n;
  string S;
  vector<int> sa, rank;

public:
  suffix_array(const string &S_) : n(S_.size()), S(S_), sa(n + 1), rank(n + 1) {
    for (int i = 0; i <= n; i++) {
      sa[i] = i;
      rank[i] = i < n ? S[i] : -1;
    }
    vector<int> tmp(n + 1);
    for (int k = 1; k <= n; k *= 2) {
      auto Compare_SA = [&](int i, int j) {
        if (rank[i] != rank[j])
          return rank[i] < rank[j];
        int ri = i + k <= n ? rank[i + k] : -1;
        int rj = j + k <= n ? rank[j + k] : -1;
        return ri < rj;
      };
      sort(sa.begin(), sa.end(), Compare_SA);
      tmp[sa[0]] = 0;
      for (int i = 1; i <= n; i++)
        tmp[sa[i]] = tmp[sa[i - 1]] + (Compare_SA(sa[i - 1], sa[i]) ? 1 : 0);
      for (int i = 0; i <= n; i++)
        rank[i] = tmp[i];
    }
  }
  bool is_contain(const string &T) {
    int lb = 0, ub = n;
    while (ub - lb > 1) {
      int m = (lb + ub) / 2;
      if (S.compare(sa[m], T.length(), T) < 0)
        lb = m;
      else
        ub = m;
    }
    return S.compare(sa[ub], T.length(), T) == 0;
  }
  vector<int> get_lcp() {
    for (int i = 0; i <= n; i++)
      rank[sa[i]] = i;
    int h = 0;
    vector<int> lcp(n + 1);
    for (int i = 0; i < n; i++) {
      int j = sa[rank[i] - 1];

      if (h > 0)
        h--;
      for (; j + h < n && i + h < n; h++) {
        if (S[j + h] != S[i + h])
          break;
      }
      lcp[rank[i] - 1] = h;
    }
    return lcp;
  }
};

int main() {
  ios::sync_with_stdio(false), cin.tie(0);
  int Q;
  string T;
  cin >> T;
  suffix_array sa(T);
  cin >> Q;
  while (Q--) {
    string P;
    cin >> P;
    printf("%d\\n", (int)sa.is_contain(P));
  }
  return 0;
}


Error: MLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

class Aho_Corasick {
  static const int var = 62; // ??????????¨??????°
  static int trans(char c) {
    if ('A' <= c && c <= 'Z') {
      return c - 'A';
    }
    if ('a' <= c && c <= 'z') {
      return c - 'a' + 26;
    }
    if ('0' <= c && c <= '9') {
      return c - '0' + 52;
    }
    exit(EXIT_FAILURE);
  }
  struct node {
    node *no;
    vector<node *> next;
    vector<int> matched;
    node() : no(nullptr), next(var, nullptr) {}
    ~node() {
      for (auto ite : next)
        if (ite != this && ite != nullptr)
          delete ite;
    }
  };
  vector<int> unite(const vector<int> &a, const vector<int> &b) {
    vector<int> res;
    set_union(a.begin(), a.end(), b.begin(), b.end(), back_inserter(res));
    return res;
  }
  int K;
  node *root;

public:
  Aho_Corasick(const vector<string> &Ts) : K(Ts.size()), root(new node) {
    node *now;
    root->no = root;
    for (int i = 0; i < K; i++) {
      auto &T = Ts[i];
      now = root;
      for (auto c : T) {
        if (now->next[trans(c)] == nullptr) {
          now->next[trans(c)] = new node;
        }
        now = now->next[trans(c)];
      }
      now->matched.push_back(i);
    }
    queue<node *> q;
    for (int i = 0; i < var; i++) {
      if (root->next[i] == nullptr) {
        root->next[i] = root;
      } else {
        root->next[i]->no = root;
        q.push(root->next[i]);
      }
    }
    while (!q.empty()) {
      now = q.front();
      q.pop();
      for (int i = 0; i < var; i++) {
        if (now->next[i] != nullptr) {
          node *nx = now->no;
          while (nx->next[i] == nullptr) {
            nx = nx->no;
          }
          now->next[i]->no = nx->next[i];
          now->next[i]->matched =
              unite(now->next[i]->matched, nx->next[i]->matched);
          q.push(now->next[i]);
        }
      }
    }
  }
  ~Aho_Corasick() { delete root; }
  vector<int> count(const string &S) {
    vector<int> res(K);
    node *now = root;
    for (auto c : S) {
      while (now->next[trans(c)] == nullptr) {
        now = now->no;
      }
      now = now->next[trans(c)];
      for (auto k : now->matched) {
        res[k]++;
      }
    }
    return res;
  }
};

int main() {
  string S;
  int M;
  cin >> S >> M;
  vector<string> C(M);
  for (int i = 0; i < M; i++) {
    cin >> C[i];
  }
  Aho_Corasick aho(C);
  auto cnt = aho.count(S);
  for (auto t : cnt) {
    cout << (t != 0) << endl;
  }
  return 0;
}