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

#include <algorithm>
#include <cassert>
#include <cstdio>
#include <iostream>
#include <string>
#include <vector>

#define REP(i, n) for (int i = 0; i < int(n); ++i)
#define ALL(A) (A).begin(), (A).end()
#define SZ(A) int(A.size())

using namespace std;

typedef unsigned long long ull;

struct RollingHash {
  static const ull p = 100000007;
  string s;
  int n;
  // vector<ull> pow, phash;
  ull *pow, *phash;

  RollingHash(const string &s) : s(s), n(SZ(s)) {
    pow = new ull[n + 1];
    phash = new ull[n + 1];
    pow[0] = 1, phash[0] = 0;
    REP(i, n) {
      phash[i + 1] = s[i] + phash[i] * p;
      pow[i + 1] = pow[i] * p;
    }
  }

  ~RollingHash() { free(pow), free(phash); }

  inline bool operator()(const int &i, const int &j) const {
    const int k = lcp(i, j);
    return i + k >= n ? true : j + k >= n ? false : s[i + k] <= s[j + k];
  }

  /*
  static ull hash(const string &t) {
    ull h=0;
    REP(i,SZ(t))h=t[i]+h*p;
    return h;
  }
  */

  inline ull hash(const int &b, const int &e) const {
    return phash[e] - phash[b] * pow[e - b];
  }
  /*
  inline int find(string t) {
    int w=t.size(),count=0;
    if(w > SZ(s))return 0;
    ull h=hash(t);
    REP(i,n-w+1)count+=(hash(i,i+w)==h);
    return count;
  }
  */

  inline int lcp(const int &i, const int &j) const {
    int l = 0, r = n - max(i, j) + 1;
    while (r - l > 1) {
      const int m = (l + r) >> 1;
      (hash(i, i + m) == hash(j, j + m) ? l : r) = m;
    }
    return l;
  }
};
/*
void mergesort(const int& n,int *a, const RollingHash& rh){
  if(n>1){
    int nb=n/2,nc=n-nb,b[nb],c[nc];
    REP(i,nb)b[i]=a[i];
    REP(i,nc)c[i]=a[nb+i];
      //vector<int> b(a.begin(), a.begin()+n/2), c(a.begin()+n/2, a.end());
    mergesort(nb,b,rh), mergesort(nc,c,rh);
    for(int i=0,j=0,k=0;i<n;i++){
      if(k>=nc)a[i]=b[j++];
      else if(j>=nb)a[i]=c[k++];
      else if(rh(b[j],c[k]))a[i]=b[j++];
      else a[i]=c[k++];
    }
  }
}
*/

int L[1000000], R[1000000];

inline void merge(int *A, const int left, const int mid, const int right,
                  const RollingHash &rh) {
  const int n1 = mid - left, n2 = right - mid;
  REP(i, n1) L[i] = A[left + i];
  REP(i, n2) R[i] = A[mid + i];
  for (int k = left, i = 0, j = 0; k < right; k++) {
    if (n2 <= j)
      A[k] = L[i++];
    else if (n1 <= i)
      A[k] = R[j++];
    else
      A[k] = rh(L[i], R[j]) ? L[i++] : R[j++];
  }
}

void mergeSort(int *A, const int left, const int right, const RollingHash &rh) {
  if (left + 1 < right) {
    const int mid = (left + right) >> 1;
    mergeSort(A, left, mid, rh);
    mergeSort(A, mid, right, rh);
    merge(A, left, mid, right, rh);
  }
}

// O(n (log n)^2)
vector<int> suffixArray(const RollingHash &rh) {
  int n = rh.n + 1, sa[n];
  REP(i, n) sa[i] = i;
  // mergesort(n,sa,rh);
  mergeSort(sa, 0, n, rh);
  vector<int> res(n);
  REP(i, n) res[i] = sa[i];
  return res;
}

bool contain(const string &S, const vector<int> &sa, const string &T) {
  int a = 0, b = SZ(S);
  while (b - a > 1) {
    const int c = (a + b) / 2;
    (S.compare(sa[c], T.length(), T) < 0 ? a : b) = c;
  }
  return S.compare(sa[b], T.length(), T) == 0;
}

int main(void) {

  char str[1000002];
  string s, t;
  scanf("%s", str);
  s = str;

  RollingHash rh = RollingHash(s);
  vector<int> sa = suffixArray(rh);

  int n;
  cin >> n;

  while (n--) {
    scanf("%s", str);
    t = str;
    printf("%d\\n", contain(s, sa, t));
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cassert>
#include <cstdio>
#include <iostream>
#include <string>
#include <vector>

#define REP(i, n) for (int i = 0; i < int(n); ++i)
#define ALL(A) (A).begin(), (A).end()
#define SZ(A) int(A.size())

using namespace std;

typedef unsigned long long ull;

struct RollingHash {
  static const ull p = 100000007;
  string s;
  int n;
  // vector<ull> pow, phash;
  ull *pow, *phash;

  RollingHash(const string &s) : s(s), n(SZ(s)) {
    pow = new ull[n + 1];
    phash = new ull[n + 1];
    pow[0] = 1, phash[0] = 0;
    REP(i, n) {
      phash[i + 1] = s[i] + phash[i] * p;
      pow[i + 1] = pow[i] * p;
    }
  }

  ~RollingHash() { free(pow), free(phash); }

  inline bool operator()(const int &i, const int &j) const {
    const int k = lcp(i, j);
    return i + k >= n ? true : j + k >= n ? false : s[i + k] <= s[j + k];
  }

  /*
  static ull hash(const string &t) {
    ull h=0;
    REP(i,SZ(t))h=t[i]+h*p;
    return h;
  }
  */

  inline ull hash(const int &b, const int &e) const {
    return phash[e] - phash[b] * pow[e - b];
  }
  /*
  inline int find(string t) {
    int w=t.size(),count=0;
    if(w > SZ(s))return 0;
    ull h=hash(t);
    REP(i,n-w+1)count+=(hash(i,i+w)==h);
    return count;
  }
  */

  inline int lcp(const int &i, const int &j) const {
    int l = 0, r = n - max(i, j) + 1;
    while (r - l > 1) {
      const int m = (l + r) / 2;
      (hash(i, i + m) == hash(j, j + m) ? l : r) = m;
    }
    return l;
  }
};
/*
void mergesort(const int& n,int *a, const RollingHash& rh){
  if(n>1){
    int nb=n/2,nc=n-nb,b[nb],c[nc];
    REP(i,nb)b[i]=a[i];
    REP(i,nc)c[i]=a[nb+i];
      //vector<int> b(a.begin(), a.begin()+n/2), c(a.begin()+n/2, a.end());
    mergesort(nb,b,rh), mergesort(nc,c,rh);
    for(int i=0,j=0,k=0;i<n;i++){
      if(k>=nc)a[i]=b[j++];
      else if(j>=nb)a[i]=c[k++];
      else if(rh(b[j],c[k]))a[i]=b[j++];
      else a[i]=c[k++];
    }
  }
}
*/

int L[1000000], R[1000000];

inline void merge(int *A, const int left, const int mid, const int right,
                  const RollingHash &rh) {
  const int n1 = mid - left, n2 = right - mid;
  REP(i, n1) L[i] = A[left + i];
  REP(i, n2) R[i] = A[mid + i];
  for (int k = left, i = 0, j = 0; k < right; k++) {
    if (n2 <= j)
      A[k] = L[i++];
    else if (n1 <= i)
      A[k] = R[j++];
    else
      A[k] = rh(L[i], R[j]) ? L[i++] : R[j++];
  }
}

void mergeSort(int *A, const int left, const int right, const RollingHash &rh) {
  if (left + 1 < right) {
    const int mid = (left + right) >> 1;
    mergeSort(A, left, mid, rh);
    mergeSort(A, mid, right, rh);
    merge(A, left, mid, right, rh);
  }
}

// O(n (log n)^2)
vector<int> suffixArray(const RollingHash &rh) {
  int n = rh.n + 1, sa[n];
  REP(i, n) sa[i] = i;
  // mergesort(n,sa,rh);
  mergeSort(sa, 0, n, rh);
  vector<int> res(n);
  REP(i, n) res[i] = sa[i];
  return res;
}

bool contain(const string &S, const vector<int> &sa, const string &T) {
  int a = 0, b = SZ(S);
  while (b - a > 1) {
    const int c = (a + b) / 2;
    (S.compare(sa[c], T.length(), T) < 0 ? a : b) = c;
  }
  return S.compare(sa[b], T.length(), T) == 0;
}

int main(void) {

  char str[1000002];
  string s, t;
  scanf("%s", str);
  s = str;

  RollingHash rh = RollingHash(s);
  vector<int> sa = suffixArray(rh);

  int n;
  cin >> n;

  while (n--) {
    scanf("%s", str);
    t = str;
    printf("%d\\n", contain(s, sa, t));
  }

  return 0;
}