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

#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef unsigned long long ull;
struct RollingHash2D {
  struct RollingHash {
    string S;
    ull B;
    vector<ull> hash, p;
    int len;
    RollingHash() {}
    RollingHash(string S, ull B = 1000000007LL) : S(S), B(B) { init(); };
    void init() {
      len = S.length();
      hash.resize(len + 1);
      p.resize(len + 1);
      hash[0] = 0;
      p[0] = 1;
      for (int i = 0; i < len; i++) {
        hash[i + 1] = hash[i] * B + S[i];
        p[i + 1] = p[i] * B;
      }
    }
    // S[l,r)
    ull find(int l, int r) { return hash[r] - hash[l] * p[r - l]; }
  };
  vector<string> S;
  vector<RollingHash> rh;
  vector<vector<ull>> hash;
  vector<ull> p;
  int h, w, r, c;
  ull B;
  RollingHash2D() {}
  RollingHash2D(vector<string> S, int r, int c, ull B = 9973)
      : S(S), r(r), c(c), B(B) {
    init();
  };
  void init() {
    h = S.size();
    w = S[0].size();
    hash.resize(h + 1, vector<ull>(w - c + 1, 0));
    rh.resize(h);
    for (int i = 0; i < h; i++)
      rh[i] = RollingHash(S[i]);
    p.resize(h + 1);
    p[0] = 1;
    for (int i = 0; i < h; i++)
      p[i + 1] = p[i] * B;
    for (int j = 0; j < w - c + 1; j++) {
      hash[0][j] = 0;
      for (int i = 0; i < h; i++)
        hash[i + 1][j] = hash[i][j] * B + rh[i].find(j, j + c);
    }
  }
  // S[l,r)
  ull find(int i, int j) { return hash[i + r][j] - hash[i][j] * p[r]; }
};
signed main() {
  int h, w;
  cin >> h >> w;
  vector<string> s(h);
  for (int i = 0; i < h; i++)
    cin >> s[i];
  int r, c;
  cin >> r >> c;
  vector<string> t(r);
  for (int i = 0; i < r; i++)
    cin >> t[i];
  RollingHash2D srh(s, r, c);
  RollingHash2D trh(t, r, c);
  for (int i = 0; i < h - r + 1; i++) {
    for (int j = 0; j < w - c + 1; j++) {
      if (srh.find(i, j) == trh.find(0, 0))
        cout << i << " " << j << endl;
    }
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef unsigned long long ull;
struct RollingHash {
  string S;
  ull B;
  vector<ull> hash, p;
  int len;
  RollingHash() {}
  RollingHash(string S, ull B = 1000000007LL) : S(S), B(B) { init(); };
  void init() {
    len = S.length();
    hash.resize(len + 1);
    p.resize(len + 1);
    hash[0] = 0;
    p[0] = 1;
    for (int i = 0; i < len; i++) {
      hash[i + 1] = hash[i] * B + S[i];
      p[i + 1] = p[i] * B;
    }
  }
  // S[l,r)
  ull find(int l, int r) { return hash[r] - hash[l] * p[r - l]; }
};
ull mhash(vector<ull> v, ull k) {
  ull B = 1000000007LL + k * 4;
  ull res = 0;
  for (int i = 0; i < (int)v.size(); i++)
    res = (res * 255 + v[i]) % B;
  return res;
}
ull mhash2(vector<ull> v, ull k) {
  ull B = 1000000007LL + k * 4;
  ull res = 0;
  for (int i = 0; i < (int)v.size(); i++)
    res = res * B + v[i];
  return res;
}
const int CNT = 2;
signed main() {
  int h, w;
  cin >> h >> w;
  string s[h];
  for (int i = 0; i < h; i++)
    cin >> s[i];
  RollingHash srh[CNT][h];
  for (int k = 0; k < CNT; k++) {
    for (int i = 0; i < h; i++) {
      srh[k][i].S = s[i];
      srh[k][i].B = 1000000007LL + (2 * k);
      srh[k][i].init();
    }
  }
  int r, c;
  cin >> r >> c;
  string t[r];
  for (int i = 0; i < r; i++)
    cin >> t[i];
  RollingHash trh[CNT][r];
  vector<ull> v[CNT];
  for (int k = 0; k < CNT; k++) {
    for (int i = 0; i < r; i++) {
      trh[k][i].S = t[i];
      trh[k][i].B = 1000000007LL + (2 * k);
      trh[k][i].init();
      v[k].push_back(trh[k][i].find(0, c));
    }
  }
  ull base[CNT];
  for (int k = 0; k < CNT; k++)
    base[k] = mhash(v[k], k);
  ull base2[CNT];
  for (int k = 0; k < CNT; k++)
    base2[k] = mhash2(v[k], k);
  for (int i = 0; i < h - r + 1; i++) {
    for (int j = 0; j < w - c + 1; j++) {
      bool flg = 1;
      for (int k = 0; k < CNT; k++) {
        vector<ull> u;
        for (int l = 0; l < r; l++)
          u.push_back(srh[k][i + l].find(j, j + c));
        flg &= (mhash(u, k) == base[k]);
      }
      for (int k = 0; k < CNT; k++) {
        vector<ull> u;
        for (int l = 0; l < r; l++)
          u.push_back(srh[k][i + l].find(j, j + c));
        flg &= (mhash2(u, k) == base2[k]);
      }
      if (flg)
        cout << i << " " << j << endl;
    }
  }
  return 0;
}