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

#include <cstdio>
#include <cstring>
#include <iostream>
#include <set>
#define REP(i, n) for (int i = 0; i < (int)(n); i++)

using namespace std;

int h, w, p;
int g[1000][1000];
int pat[100][100];
int tmp[100][100];

int decode(char c) {
  if ('A' <= c && c <= 'Z')
    return c - 'A';
  if ('a' <= c && c <= 'z')
    return c - 'a' + 26;
  if ('0' <= c && c <= '9')
    return c - '0' + 52;
  if (c == '+')
    return 62;
  if (c == '/')
    return 63;
  return -1;
}

template <int N> void get(int (&dist)[N][N], int h, int w) {
  REP(i, h) {
    char buff[1012];
    scanf("%s", buff);

    REP(j, w) {
      int a = j / 6;
      int b = j % 6;
      dist[i][j] = (decode(buff[a]) & (1 << (5 - b))) != 0 ? 1 : 0;
    }
  }
}

struct Hash {
  unsigned long long h[2];
  Hash() {}
  Hash(int *p, int len) {
    h[0] = h[1] = 0;
    REP(i, len)
    if (p[i])
      h[i / 64] |= (1ll << (i % 64));
  }
};

inline bool operator==(const Hash &lhs, const Hash &rhs) {
  return lhs.h[0] == rhs.h[0] && lhs.h[1] == rhs.h[1];
}
inline bool operator!=(const Hash &lhs, const Hash &rhs) {
  return !(lhs == rhs);
}

int ans[1000][1000];
Hash gh[1000][1000];
Hash ph[100];

int main() {
  while (scanf("%d%d%d", &w, &h, &p), w + h + p) {
    REP(i, h) REP(j, w) ans[i][j] = 0;

    get(g, h, w);
    get(pat, p, p);

    REP(i, h) REP(j, w - p + 1) gh[i][j] = Hash(&g[i][j], p);

    int pcnt = 0;

    REP(i, p) REP(j, p) if (pat[i][j]) pcnt++;
    REP(i, h) {
      int t = 0;
      REP(j, w) {
        t += g[i][j];
        if (j >= p - 1) {
          int tt = g[i][j - p + 1];
          g[i][j - p + 1] = t;
          t -= tt;
        }
      }
    }
    REP(j, w) {
      int t = 0;
      REP(i, h) {
        t += g[i][j];
        if (i >= p - 1) {
          int tt = g[i - p + 1][j];
          g[i - p + 1][j] = t;
          if (g[i - p + 1][j] != pcnt)
            ans[i - p + 1][j] = 1;
          t -= tt;
        }
      }
    }

    int cnt = 0;
    REP(m, 2) {
      REP(r, 4) {
        REP(i, p) ph[i] = Hash(pat[i], p);

        // puts("p:");REP(i,p){REP(j,p) printf("%d", pat[i][j]);puts("");}

        REP(i, h - p + 1) REP(j, w - p + 1) if (ans[i][j] == 0) {
          REP(k, p) if (gh[i + k][j] != ph[k]) goto next;
          ans[i][j] = 1;
          cnt++;
        next:;
        }

        // rotate
        REP(i, p) REP(j, p) tmp[i][j] = pat[i][j];
        REP(i, p) REP(j, p) pat[i][j] = tmp[p - j - 1][i];
        bool diff = false;
        REP(i, p) REP(j, p) if (pat[i][j] != tmp[i][j]) diff = true;
        if (!diff)
          r = 4;
      }
      // mirror
      REP(i, p) REP(j, p) tmp[i][j] = pat[i][j];
      REP(i, p) REP(j, p / 2) swap(pat[i][j], pat[i][p - j - 1]);
      bool diff = false;
      REP(i, p) REP(j, p) if (pat[i][j] != tmp[i][j]) diff = true;
      if (!diff)
        m = 4;
    }

    printf("%d\\n", cnt);
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <set>
#define REP(i, n) for (int i = 0; i < (int)(n); i++)

using namespace std;

int h, w, p;
int g[1000][1000];
int pat[100][100];
int tmp[100][100];

int decode(char c) {
  if ('A' <= c && c <= 'Z')
    return c - 'A';
  if ('a' <= c && c <= 'z')
    return c - 'a' + 26;
  if ('0' <= c && c <= '9')
    return c - '0' + 52;
  if (c == '+')
    return 62;
  if (c == '/')
    return 63;
  return -1;
}

template <int N> void get(int (&dist)[N][N], int h, int w) {
  REP(i, h) {
    char buff[1012];
    scanf("%s", buff);

    REP(j, w) {
      int a = j / 6;
      int b = j % 6;
      dist[i][j] = (decode(buff[a]) & (1 << (5 - b))) != 0 ? 1 : 0;
    }
  }
}

struct Hash {
  unsigned long long h[2];
  Hash() {}
  Hash(int *p, int len) {
    h[0] = h[1] = 0;
    REP(i, len)
    if (p[i])
      h[i / 64] |= (1ll << (i % 64));
  }
};

inline bool operator==(const Hash &lhs, const Hash &rhs) {
  return lhs.h[0] == rhs.h[0] && lhs.h[1] == rhs.h[1];
}
inline bool operator!=(const Hash &lhs, const Hash &rhs) {
  return !(lhs == rhs);
}

int ans[1000][1000];
Hash gh[1000][1000];
Hash ph[100];

int main() {
  while (scanf("%d%d%d", &w, &h, &p), w + h + p) {
    REP(i, h) REP(j, w) ans[i][j] = 0;

    get(g, h, w);
    get(pat, p, p);

    REP(i, h) REP(j, w - p + 1) gh[i][j] = Hash(&g[i][j], p);

    int cnt = 0;
    REP(m, 2) {
      REP(r, 4) {
        REP(i, p) ph[i] = Hash(pat[i], p);

        // puts("p:");REP(i,p){REP(j,p) printf("%d", pat[i][j]);puts("");}

        REP(i, h - p + 1) REP(j, w - p + 1) if (ans[i][j] == 0) {
          REP(k, p) if (gh[i + k][j] != ph[k]) goto next;
          ans[i][j] = 1;
          cnt++;
        next:;
        }

        if (cnt == h * w)
          goto end;

        // rotate
        REP(i, p) REP(j, p) tmp[i][j] = pat[i][j];
        REP(i, p) REP(j, p) pat[i][j] = tmp[p - j - 1][i];
      }
      // mirror
      REP(i, p) REP(j, p / 2) swap(pat[i][j], pat[i][p - j - 1]);
    }

  end:;
    printf("%d\\n", cnt);
  }
  return 0;
}