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

#include <bits/stdc++.h>
using namespace std;
#define FOR(i, k, n) for (int i = (int)(k); i < (int)(n); i++)
#define REP(i, n) FOR(i, 0, n)
#define ALL(a) a.begin(), a.end()
#define MS(m, v) memset(m, v, sizeof(m))
#define D10 fixed << setprecision(10)
typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef vector<string> vs;
typedef pair<int, int> pii;
const int MOD = 1000000007;
const int INF = MOD + 1;
const ld EPS = 1e-12;
template <class T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template <class T> T &chmax(T &a, const T &b) { return a = max(a, b); }

/*--------------------template--------------------*/
vector<vi> fld;
vector<vi> org;
vector<vector<vi>> pat;

vi dig(int n) {
  vi res;
  int t = 32;
  while (t > 0) {
    if (n >= t) {
      n -= t;
      res.push_back(1);
    } else
      res.push_back(0);

    t /= 2;
  }
  return res;
}

vi dec(string s) {
  vi res;
  REP(i, s.size()) {
    int val;
    if (isupper(s[i]))
      val = s[i] - 'A';
    else if (islower(s[i]))
      val = s[i] - 'a' + 26;
    else if (isdigit(s[i]))
      val = s[i] - '0' + 52;
    else if (s[i] == '+')
      val = 62;
    else if (s[i] == '/')
      val = 63;
    else
      assert(false);
    vi tmp = dig(val);
    res.insert(res.end(), ALL(tmp));
  }
  return res;
}

void print() {

  REP(i, fld.size()) {
    REP(j, fld[0].size()) { cout << fld[i][j]; }
    puts("");
  }
  puts("");
  REP(i, pat.size()) {
    REP(j, pat[0].size()) {
      REP(k, pat[0][0].size()) cout << pat[i][j][k];
      puts("");
    }
    puts("");
  }
  puts("");
}

void make_pattern() {
  int n = org.size();
  pat.resize(8, vector<vi>(n, vi(n)));
  pat[0] = org;
  REP(k, 3) REP(i, n) REP(j, n) pat[k + 1][i][j] = pat[k][n - j - 1][i];
  REP(k, 4) REP(i, n) REP(j, n) pat[k + 4][i][j] = pat[k][i][n - j - 1];
  sort(ALL(pat));
  pat.erase(unique(ALL(pat)), pat.end());
}

const ll mod[] = {999999937, 1000000007}, base[] = {10000103, 9999999};

struct RollingHash {
  int n;
  vector<ll> hs[2], pw[2];
  RollingHash(){};
  RollingHash(const vi &s) {
    n = s.size();
    REP(i, 2) {
      hs[i].assign(n + 1, 0);
      pw[i].assign(n + 1, 0);
      hs[i][0] = 0;
      pw[i][0] = 1;
      REP(j, n) {
        pw[i][j + 1] = pw[i][j] * base[i] % mod[i];
        hs[i][j + 1] = (hs[i][j] * base[i] + s[j] + 99999) % mod[i];
      }
    }
  }

  ll hash(int l, int r, int i) {
    return ((hs[i][r] - hs[i][l] * pw[i][r - l]) % mod[i] + mod[i]) % mod[i];
  }

  bool match(int l1, int r1, int l2, int r2) {
    return (hash(l1, r1, 0) == hash(l2, r2, 0)) &&
           (hash(l1, r1, 1) == hash(l2, r2, 1));
  }
};

int main() {
  int w, h, p;
  while (cin >> w >> h >> p, w) {
    fld.clear();
    org.clear();
    pat.clear();
    REP(i, h) {
      string s;
      cin >> s;
      vi tmp = dec(s);
      while (tmp.size() > w)
        tmp.pop_back();
      fld.push_back(tmp);
    }
    REP(i, p) {
      string s;
      cin >> s;
      vi tmp = dec(s);
      while (tmp.size() > p)
        tmp.pop_back();
      org.push_back(tmp);
    }
    make_pattern();
    //		print();
    vector<RollingHash> vrh(h);
    REP(i, h) vrh[i] = RollingHash(fld[i]);
    vector<vi> vhs(w - p + 1, vi(h));
    REP(i, h) REP(j, w - p + 1) { vhs[j][i] = vrh[i].hash(j, j + p, 0); }
    map<ll, int> mp;
    REP(i, w - p + 1) {
      RollingHash tmp(vhs[i]);
      REP(j, h - p + 1) {
        ll t = tmp.hash(j, j + p, 1);
        mp[t]++;
      }
    }
    ll ans = 0;
    REP(i, pat.size()) {
      vi hsx(p);
      REP(j, p) { hsx[j] = RollingHash(pat[i][j]).hash(0, p, 0); }
      ll hs = RollingHash(hsx).hash(0, p, 1);
      ans += mp[hs];
      ans %= MOD;
    }
    cout << ans << endl;
  }
  return 0;
}

Error: MLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
#define FOR(i, k, n) for (int i = (int)(k); i < (int)(n); i++)
#define REP(i, n) FOR(i, 0, n)
#define ALL(a) a.begin(), a.end()
#define MS(m, v) memset(m, v, sizeof(m))
#define D10 fixed << setprecision(10)
typedef long long ll;
typedef long double ld;
typedef vector<ll> vi;
typedef vector<string> vs;
typedef pair<int, int> pii;
const int MOD = 1000000007;
const int INF = MOD + 1;
const ld EPS = 1e-12;
template <class T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template <class T> T &chmax(T &a, const T &b) { return a = max(a, b); }

/*--------------------template--------------------*/
vector<vi> fld;
vector<vi> org;
vector<vector<vi>> pat;

vi dig(int n) {
  vi res;
  int t = 32;
  while (t > 0) {
    if (n >= t) {
      n -= t;
      res.push_back(1);
    } else
      res.push_back(0);

    t /= 2;
  }
  return res;
}

vi dec(string s) {
  vi res;
  REP(i, s.size()) {
    int val;
    if (isupper(s[i]))
      val = s[i] - 'A';
    else if (islower(s[i]))
      val = s[i] - 'a' + 26;
    else if (isdigit(s[i]))
      val = s[i] - '0' + 52;
    else if (s[i] == '+')
      val = 62;
    else if (s[i] == '/')
      val = 63;
    else
      assert(false);
    vi tmp = dig(val);
    res.insert(res.end(), ALL(tmp));
  }
  return res;
}

void print() {

  REP(i, fld.size()) {
    REP(j, fld[0].size()) { cout << fld[i][j]; }
    puts("");
  }
  puts("");
  REP(i, pat.size()) {
    REP(j, pat[0].size()) {
      REP(k, pat[0][0].size()) cout << pat[i][j][k];
      puts("");
    }
    puts("");
  }
  puts("");
}

void make_pattern() {
  int n = org.size();
  pat.resize(8, vector<vi>(n, vi(n)));
  pat[0] = org;
  REP(k, 3) REP(i, n) REP(j, n) pat[k + 1][i][j] = pat[k][n - j - 1][i];
  REP(k, 4) REP(i, n) REP(j, n) pat[k + 4][i][j] = pat[k][i][n - j - 1];
  sort(ALL(pat));
  pat.erase(unique(ALL(pat)), pat.end());
}

const ll mod[] = {999999937, 1000000007}, base[] = {10000103, 9999999};

struct RollingHash {
  int n;
  vector<ll> hs[2], pw[2];
  RollingHash(){};
  RollingHash(const vi &s) {
    n = s.size();
    REP(i, 2) {
      hs[i].assign(n + 1, 0);
      pw[i].assign(n + 1, 0);
      hs[i][0] = 0;
      pw[i][0] = 1;
      REP(j, n) {
        pw[i][j + 1] = pw[i][j] * base[i] % mod[i];
        hs[i][j + 1] = (hs[i][j] * base[i] + s[j] + 99999) % mod[i];
      }
    }
  }

  ll hash(int l, int r, int i) {
    return ((hs[i][r] - hs[i][l] * pw[i][r - l]) % mod[i] + mod[i]) % mod[i];
  }

  bool match(int l1, int r1, int l2, int r2) {
    return (hash(l1, r1, 0) == hash(l2, r2, 0)) &&
           (hash(l1, r1, 1) == hash(l2, r2, 1));
  }
};

int main() {
  int w, h, p;
  while (cin >> w >> h >> p, w) {
    fld.clear();
    org.clear();
    pat.clear();
    REP(i, h) {
      string s;
      cin >> s;
      vi tmp = dec(s);
      while (tmp.size() > w)
        tmp.pop_back();
      fld.push_back(tmp);
    }
    REP(i, p) {
      string s;
      cin >> s;
      vi tmp = dec(s);
      while (tmp.size() > p)
        tmp.pop_back();
      org.push_back(tmp);
    }
    make_pattern();
    //		print();
    vector<RollingHash> vrh(h);
    REP(i, h) vrh[i] = RollingHash(fld[i]);
    vector<vi> vhs(w - p + 1, vector<ll>(h));
    REP(i, h) REP(j, w - p + 1) { vhs[j][i] = vrh[i].hash(j, j + p, 0); }
    map<ll, int> mp;
    REP(i, w - p + 1) {
      RollingHash tmp(vhs[i]);
      REP(j, h - p + 1) {
        ll t = tmp.hash(j, j + p, 1);
        mp[t]++;
      }
    }
    ll ans = 0;
    REP(i, pat.size()) {
      vi hsx(p);
      REP(j, p) { hsx[j] = RollingHash(pat[i][j]).hash(0, p, 0); }
      ll hs = RollingHash(hsx).hash(0, p, 1);
      ans += mp[hs];
      ans %= MOD;
    }
    cout << ans << endl;
  }
  return 0;
}