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

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <fstream>
#include <iostream>
#include <string>

using namespace std;

typedef unsigned long long ll;

ll p[1200];
const ll P = 1000000007;
class RollingHash {
public:
  ll a[1200];
  RollingHash(char *fp, int W) {
    a[0] = 0;
    for (int j = 1; j <= W; j++)
      a[j] = a[j - 1] * P + (fp[j - 1]);
  }
  RollingHash(){};
  ll getHashValue(int x, int y) { return a[y + 1] - a[x] * p[y - x + 1]; }
};
int w, h, m;
char field[1200][1200];
char pattern[110][110];
void rotatePattern() {
  char nxtPattern[1200][1200];
  for (int i = 0; i < m; i++)
    for (int j = 0; j < m; j++)
      nxtPattern[i][m - 1 - j] = pattern[j][i];
  for (int i = 0; i < m; i++)
    for (int j = 0; j < m; j++)
      pattern[i][j] = nxtPattern[i][j];
}
void reversePattern() {
  char nxtPattern[1200][1200];
  for (int i = 0; i < m; i++)
    for (int j = 0; j < m; j++)
      nxtPattern[i][j] = pattern[i][m - 1 - j];
  for (int i = 0; i < m; i++)
    for (int j = 0; j < m; j++)
      pattern[i][j] = nxtPattern[i][j];
}
int charToInt(char ch) {
  if (ch >= 'A' && ch <= 'Z')
    return ch - 'A';
  else if (ch >= 'a' && ch <= 'z')
    return ch - 'a' + 26;
  else if (ch >= '0' && ch <= '9')
    return ch - '0' + 52;
  else if (ch == '+')
    return 62;
  return 63;
}

RollingHash patternHash[110];
RollingHash imageHash[1200];
bool used[1200][1200];
int sums[1200][1200];
int main() {
  p[0] = 1;
  for (int i = 1; i < 1200; i++)
    p[i] = p[i - 1] * P;
  while (cin >> w >> h >> m && (w | h | m)) {
    memset(used, 0, sizeof(used));
    memset(sums, 0, sizeof(sums));
    for (int i = 0; i < h; i++) {
      int cnt = 0;
      for (int j = 0; j < (w + 5) / 6; j++) {
        char ch;
        cin >> ch;
        int a = charToInt(ch);
        string s;
        for (int k = 0; k < 6; k++) {
          if ((a >> k) & 1)
            s += '1';
          else
            s += '0';
        }
        for (int k = 0; k < s.size(); k++) {
          field[i][cnt++] = s[s.size() - 1 - k];
          if (cnt == w)
            break;
        }
      }
    }
    for (int i = 0; i < m; i++) {
      int cnt = 0;
      for (int j = 0; j < (m + 5) / 6; j++) {
        char ch;
        cin >> ch;
        int a = charToInt(ch);
        string s;
        for (int k = 0; k < 6; k++) {
          if ((a >> k) & 1)
            s += '1';
          else
            s += '0';
        }
        for (int k = 0; k < s.size(); k++) {
          pattern[i][cnt++] = s[s.size() - 1 - k];
          if (cnt == m)
            break;
        }
      }
    }
    for (int i = 0; i < h; i++)
      for (int j = 0; j < w; j++)
        sums[i + 1][j + 1] =
            sums[i][j + 1] + sums[i + 1][j] - sums[i][j] + field[i][j] - '0';
    int patternOne = 0;
    for (int i = 0; i < m; i++)
      for (int j = 0; j < m; j++)
        if (pattern[i][j] == '1')
          patternOne++;
    // imageのhash値を計算しておく
    for (int i = 0; i < h; i++)
      imageHash[i] = RollingHash(field[i], w);
    int res = 0;
    for (int rev = 0; rev < 2; rev++) {
      for (int rot = 0; rot < 4; rot++) {
        // rolling hashを計算
        for (int i = 0; i < m; i++)
          patternHash[i] = RollingHash(pattern[i], m);
        // 一致する箇所を探す
        for (int i = 0; i + m <= h; i++) {
          for (int j = 0; j + m <= w; j++) {
            if (used[i][j])
              continue;
            int cnt = sums[i + m][j + m] - sums[i + m][j] - sums[i][j + m];
            cnt += sums[i][j];
            if (cnt != patternOne)
              continue;
            bool ok = true;
            for (int k = 0; k < m; k++) {
              if (!(imageHash[i + k].getHashValue(j, j + m - 1) ==
                    patternHash[k].getHashValue(0, m - 1))) {
                ok = false;
                break;
              }
            }
            if (ok) {
              res++;
              used[i][j] = true;
            }
          }
        }
        rotatePattern();
      }
      reversePattern();
    }
    cout << res << endl;
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <fstream>
#include <iostream>
#include <string>

using namespace std;

typedef unsigned long long ll;

ll p[1200];
const ll P = 1000000007;
class RollingHash {
public:
  ll a[1200];
  RollingHash(char *fp, int W) {
    a[0] = 0;
    for (int j = 1; j <= W; j++)
      a[j] = a[j - 1] * P + (fp[j - 1]);
  }
  RollingHash(){};
  ll getHashValue(int x, int y) { return a[y + 1] - a[x] * p[y - x + 1]; }
};
int w, h, m;
char field[1200][1200];
char pattern[110][110];
void rotatePattern() {
  char nxtPattern[1200][1200];
  for (int i = 0; i < m; i++)
    for (int j = 0; j < m; j++)
      nxtPattern[i][m - 1 - j] = pattern[j][i];
  for (int i = 0; i < m; i++)
    for (int j = 0; j < m; j++)
      pattern[i][j] = nxtPattern[i][j];
}
void reversePattern() {
  char nxtPattern[1200][1200];
  for (int i = 0; i < m; i++)
    for (int j = 0; j < m; j++)
      nxtPattern[i][j] = pattern[i][m - 1 - j];
  for (int i = 0; i < m; i++)
    for (int j = 0; j < m; j++)
      pattern[i][j] = nxtPattern[i][j];
}
int charToInt(char ch) {
  if (ch >= 'A' && ch <= 'Z')
    return ch - 'A';
  else if (ch >= 'a' && ch <= 'z')
    return ch - 'a' + 26;
  else if (ch >= '0' && ch <= '9')
    return ch - '0' + 52;
  else if (ch == '+')
    return 62;
  return 63;
}

RollingHash patternHash[110];
RollingHash imageHash[1200];
bool used[1200][1200];
int main() {
  p[0] = 1;
  for (int i = 1; i < 1200; i++)
    p[i] = p[i - 1] * P;
  while (cin >> w >> h >> m && (w | h | m)) {
    memset(used, 0, sizeof(used));
    for (int i = 0; i < h; i++) {
      int cnt = 0;
      for (int j = 0; j < (w + 5) / 6; j++) {
        char ch;
        cin >> ch;
        int a = charToInt(ch);
        string s;
        for (int k = 0; k < 6; k++) {
          if ((a >> k) & 1)
            s += '1';
          else
            s += '0';
        }
        for (int k = 0; k < s.size(); k++) {
          field[i][cnt++] = s[s.size() - 1 - k];
          if (cnt == w)
            break;
        }
      }
    }
    for (int i = 0; i < m; i++) {
      int cnt = 0;
      for (int j = 0; j < (m + 5) / 6; j++) {
        char ch;
        cin >> ch;
        int a = charToInt(ch);
        string s;
        for (int k = 0; k < 6; k++) {
          if ((a >> k) & 1)
            s += '1';
          else
            s += '0';
        }
        for (int k = 0; k < s.size(); k++) {
          pattern[i][cnt++] = s[s.size() - 1 - k];
          if (cnt == m)
            break;
        }
      }
    }
    // imageのhash値を計算しておく
    for (int i = 0; i < h; i++)
      imageHash[i] = RollingHash(field[i], w);
    int res = 0;
    for (int rev = 0; rev < 2; rev++) {
      for (int rot = 0; rot < 4; rot++) {
        // rolling hashを計算
        for (int i = 0; i < m; i++)
          patternHash[i] = RollingHash(pattern[i], m);
        // 一致する箇所を探す
        for (int i = 0; i + m <= h; i++) {
          for (int j = 0; j + m <= w; j++) {
            if (used[i][j])
              continue;
            bool ok = true;
            for (int k = 0; k < m; k++) {
              if (!(imageHash[i + k].getHashValue(j, j + m - 1) ==
                    patternHash[k].getHashValue(0, m - 1))) {
                ok = false;
                break;
              }
            }
            if (ok) {
              res++;
              used[i][j] = true;
            }
          }
        }
        rotatePattern();
      }
      reversePattern();
    }
    cout << res << endl;
  }
  return 0;
}