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

#include <bits/stdc++.h>

using namespace std;

typedef unsigned long long ull;

typedef pair<int, ull> P;

struct RollingHash2D {
  typedef unsigned long long ull;

  struct RollingHash {
    typedef unsigned long long ull;
    string S;
    ull B;
    int len;
    vector<ull> hash, p;
    RollingHash() {}
    RollingHash(string S_, ull B_ = 1000000007LL)
        : S(S_), B(B_), len(S.length()), hash(len + 1), p(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;
  int h, w, r, c;
  ull B;
  vector<ull> p;
  vector<vector<ull>> hash;
  vector<RollingHash> rh;
  RollingHash2D() {}
  RollingHash2D(vector<string> S_, int r_, int c_, ull B_ = 1000000009LL)
      : S(S_), h(S_.size()), w(S_[0].size()), r(r_), c(c_), B(B_), p(h + 1),
        hash(h + 1, vector<ull>(w - c + 1, 0)), rh(h) {
    for (int i = 0; i < h; i++)
      rh[i] = RollingHash(S[i]);
    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);
    }
  }
  //[i,i+r) * [j,j+c)
  ull find(int i, int j) { return hash[i + r][j] - hash[i][j] * p[r]; }
};

map<char, string> M;

void init() {
  M['A'] = "000000";
  M['B'] = "000001";
  M['C'] = "000010";
  M['D'] = "000011";
  M['E'] = "000100";
  M['F'] = "000101";
  M['G'] = "000110";
  M['H'] = "000111";
  M['I'] = "001000";
  M['J'] = "001001";
  M['K'] = "001010";
  M['L'] = "001011";
  M['M'] = "001100";
  M['N'] = "001101";
  M['O'] = "001110";
  M['P'] = "001111";
  M['Q'] = "010000";
  M['R'] = "010001";
  M['S'] = "010010";
  M['T'] = "010011";
  M['U'] = "010100";
  M['V'] = "010101";
  M['W'] = "010110";
  M['X'] = "010111";
  M['Y'] = "011000";
  M['Z'] = "011001";
  M['a'] = "011010";
  M['b'] = "011011";
  M['c'] = "011100";
  M['d'] = "011101";
  M['e'] = "011110";
  M['f'] = "011111";
  M['g'] = "100000";
  M['h'] = "100001";
  M['i'] = "100010";
  M['j'] = "100011";
  M['k'] = "100100";
  M['l'] = "100101";
  M['m'] = "100110";
  M['n'] = "100111";
  M['o'] = "101000";
  M['p'] = "101001";
  M['q'] = "101010";
  M['r'] = "101011";
  M['s'] = "101100";
  M['t'] = "101101";
  M['u'] = "101110";
  M['v'] = "101111";
  M['w'] = "110000";
  M['x'] = "110001";
  M['y'] = "110010";
  M['z'] = "110011";
  M['0'] = "110100";
  M['1'] = "110101";
  M['2'] = "110110";
  M['3'] = "110111";
  M['4'] = "111000";
  M['5'] = "111001";
  M['6'] = "111010";
  M['7'] = "111011";
  M['8'] = "111100";
  M['9'] = "111101";
  M['+'] = "111110";
  M['/'] = "111111";
}

vector<string> s, pat;
string t;
int w, h, p;

int main() {
  init();
  while (cin >> w >> h >> p, w) {
    s.resize(h);
    pat.resize(p);
    for (int i = 0; i < h; i++) {
      cin >> t;
      s[i] = "";
      for (int j = 0; j < t.size(); j++) {
        s[i] += M[t[j]];
      }
      if (s[i].size() > w)
        s[i].erase(s[i].begin() + w, s[i].end());
    }
    for (int i = 0; i < p; i++) {
      cin >> t;
      pat[i] = "";
      for (int j = 0; j < t.size(); j++) {
        pat[i] += M[t[j]];
      }
      if (pat[i].size() > p)
        pat[i].erase(pat[i].begin() + p, pat[i].end());
    }
    int cnt = 0;
    set<ull> st;
    RollingHash2D A(s, p, p);
    for (int rot = 0; rot < 4; rot++) {
      int H = pat.size();
      int W = pat[0].size();
      vector<string> tmp(W);
      for (int i = 0; i < W; i++) {
        for (int j = 0; j < H; j++)
          tmp[i] += " ";
      }
      for (int i = 0; i < W; i++) {
        for (int j = 0; j < H; j++) {
          tmp[i][j] = pat[H - j - 1][i];
        }
      }
      pat.clear();
      pat.resize(W);
      for (int i = 0; i < W; i++)
        pat[i] = tmp[i];

      for (int X = 0; X < 2; X++) {
        for (int i = 0; i < p; i++) {
          for (int j = 0; j < p / 2; j++) {
            swap(pat[i][j], pat[i][p - j - 1]);
          }
        }

        for (int Y = 0; Y < 2; Y++) {
          for (int j = 0; j < p; j++) {
            for (int i = 0; i < p / 2; i++) {
              swap(pat[i][j], pat[p - i - 1][j]);
            }
          }

          RollingHash2D B(pat, p, p);

          ull PB = B.find(0, 0);
          if (st.count(PB))
            continue;
          st.insert(PB);

          for (int i = 0; i <= h - p; i++) {
            for (int j = 0; j <= w - p; j++) {
              ull PA = A.find(i, j);
              if (PA == PB) {
                cnt++;
              }
            }
          }
        }
      }
    }
    cout << cnt << endl;
  }
}


Error: MLE

Fixed submission:

#include <bits/stdc++.h>

using namespace std;

typedef unsigned long long ull;

typedef pair<int, ull> P;

struct RollingHash2D {
  typedef unsigned long long ull;

  struct RollingHash {
    typedef unsigned long long ull;
    string S;
    ull B;
    int len;
    vector<ull> hash, p;
    RollingHash() {}
    RollingHash(string S_, ull B_ = 1000000007LL)
        : S(S_), B(B_), len(S.length()), hash(len + 1), p(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;
  int h, w, r, c;
  ull B;
  vector<ull> p;
  vector<vector<ull>> hash;
  vector<RollingHash> rh;
  RollingHash2D() {}
  RollingHash2D(vector<string> S_, int r_, int c_, ull B_ = 1000000009LL)
      : S(S_), h(S_.size()), w(S_[0].size()), r(r_), c(c_), B(B_), p(h + 1),
        hash(h + 1, vector<ull>(w - c + 1, 0)), rh(h) {
    for (int i = 0; i < h; i++)
      rh[i] = RollingHash(S[i]);
    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);
    }
  }
  //[i,i+r) * [j,j+c)
  ull find(int i, int j) { return hash[i + r][j] - hash[i][j] * p[r]; }
};

map<char, string> M;

void init() {
  M['A'] = "000000";
  M['B'] = "000001";
  M['C'] = "000010";
  M['D'] = "000011";
  M['E'] = "000100";
  M['F'] = "000101";
  M['G'] = "000110";
  M['H'] = "000111";
  M['I'] = "001000";
  M['J'] = "001001";
  M['K'] = "001010";
  M['L'] = "001011";
  M['M'] = "001100";
  M['N'] = "001101";
  M['O'] = "001110";
  M['P'] = "001111";
  M['Q'] = "010000";
  M['R'] = "010001";
  M['S'] = "010010";
  M['T'] = "010011";
  M['U'] = "010100";
  M['V'] = "010101";
  M['W'] = "010110";
  M['X'] = "010111";
  M['Y'] = "011000";
  M['Z'] = "011001";
  M['a'] = "011010";
  M['b'] = "011011";
  M['c'] = "011100";
  M['d'] = "011101";
  M['e'] = "011110";
  M['f'] = "011111";
  M['g'] = "100000";
  M['h'] = "100001";
  M['i'] = "100010";
  M['j'] = "100011";
  M['k'] = "100100";
  M['l'] = "100101";
  M['m'] = "100110";
  M['n'] = "100111";
  M['o'] = "101000";
  M['p'] = "101001";
  M['q'] = "101010";
  M['r'] = "101011";
  M['s'] = "101100";
  M['t'] = "101101";
  M['u'] = "101110";
  M['v'] = "101111";
  M['w'] = "110000";
  M['x'] = "110001";
  M['y'] = "110010";
  M['z'] = "110011";
  M['0'] = "110100";
  M['1'] = "110101";
  M['2'] = "110110";
  M['3'] = "110111";
  M['4'] = "111000";
  M['5'] = "111001";
  M['6'] = "111010";
  M['7'] = "111011";
  M['8'] = "111100";
  M['9'] = "111101";
  M['+'] = "111110";
  M['/'] = "111111";
}

vector<string> s, pat;
string t;
int w, h, p;

int main() {
  init();
  while (cin >> w >> h >> p, w) {
    s.resize(h);
    pat.resize(p);
    for (int i = 0; i < h; i++) {
      cin >> t;
      s[i] = "";
      for (int j = 0; j < t.size(); j++) {
        s[i] += M[t[j]];
      }
      if (s[i].size() > w)
        s[i].erase(s[i].begin() + w, s[i].end());
    }
    for (int i = 0; i < p; i++) {
      cin >> t;
      pat[i] = "";
      for (int j = 0; j < t.size(); j++) {
        pat[i] += M[t[j]];
      }
      if (pat[i].size() > p)
        pat[i].erase(pat[i].begin() + p, pat[i].end());
    }
    int cnt = 0;
    set<P> st;
    RollingHash2D A(s, p, p);
    for (int rot = 0; rot < 4; rot++) {
      int H = pat.size();
      int W = pat[0].size();
      vector<string> tmp(W);
      for (int i = 0; i < W; i++) {
        for (int j = 0; j < H; j++)
          tmp[i] += " ";
      }
      for (int i = 0; i < W; i++) {
        for (int j = 0; j < H; j++) {
          tmp[i][j] = pat[H - j - 1][i];
        }
      }
      pat.clear();
      pat.resize(W);
      for (int i = 0; i < W; i++)
        pat[i] = tmp[i];

      for (int X = 0; X < 2; X++) {
        for (int i = 0; i < p; i++) {
          for (int j = 0; j < p / 2; j++) {
            swap(pat[i][j], pat[i][p - j - 1]);
          }
        }

        for (int Y = 0; Y < 2; Y++) {
          for (int j = 0; j < p; j++) {
            for (int i = 0; i < p / 2; i++) {
              swap(pat[i][j], pat[p - i - 1][j]);
            }
          }

          RollingHash2D B(pat, p, p);

          ull PB = B.find(0, 0);

          for (int i = 0; i <= h - p; i++) {
            for (int j = 0; j <= w - p; j++) {
              if (st.count(P(i * 100000 + j, PB)))
                continue;
              st.insert(P(i * 100000 + j, PB));
              ull PA = A.find(i, j);
              if (PA == PB) {
                cnt++;
              }
            }
          }
        }
      }
    }
    cout << cnt << endl;
  }
}