Language: C++

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <math.h>
#include <assert.h>
#include <vector>

using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
static const double EPS = 1e-9;
static const double PI = acos(-1.0);

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, k, n) for (int i = (k); i < (int)(n); ++i)
#define FOREQ(i, k, n) for (int i = (k); i <= (int)(n); ++i)
#define FORIT(i, c) for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define SZ(v) (int)((v).size())
#define MEMSET(v, h) memset((v), (h), sizeof(v))
#define FIND(m, w) ((m).find(w) != (m).end())

void print(char p[1010][1010], int w, int h) {
  REP(y, h) {
    REP(x, w) {
      printf("%d ", p[y][x]);
    }
    puts("");
  }
  puts("");
}

struct PMA {
    PMA *next[200];
    int accept;
    PMA() : accept(110) { MEMSET(next, 0); }
};

PMA *root1,*root2;

PMA *buildPMA(char p[1010][1010], int size) {
    PMA *root = new PMA;
    for (int i = 0; i < size; i++) {
        PMA *t = root;
        for (int j = 0; p[i][j]; j++) {
            int c = p[i][j];
            if (t->next[c] == NULL) {
                t->next[c] = new PMA;
            }
            t = t->next[c];
        }
        if (t->accept == 110) {
            t->accept = i + 1;
        }
    }
    queue<PMA*> que;
    for (int c = 1; c < 200; c++) {
        if (root->next[c]) {
            root->next[c]->next[0] = root;
            que.push(root->next[c]);
        } else {
            root->next[c] = root;
        }
    }


    while (!que.empty()) {
        PMA *t = que.front();
        que.pop();
        for (int c = 1; c < 200; c++) {
            if (t->next[c] != NULL) {
                que.push(t->next[c]);
                PMA *r = t->next[0];
                while (!r->next[c]) {
                    r = r->next[0];
                }
                t->next[c]->next[0] = r->next[c];
            }
            //
            //
            //
        }
    }
    return root;
}

void deletePMA(PMA *root) {
    set<PMA*> visit;
    queue<PMA*> que;
    que.push(root);
    visit.insert(root);
    while (!que.empty()) {
        PMA *t = que.front();
        que.pop();
        for (int c = 1; c < 200; c++) {
            if (t->next[c] == NULL) { continue; }
            if (visit.count(t->next[c])) { continue; }
            visit.insert(t->next[c]);
            que.push(t->next[c]);
        }
    }
    FORIT(it, visit) { delete *it; }
}

char matchs[1010][1010];
int match(char *t, int n, const PMA *v, char matchs[1010][1010], int y) {
    int ret = 0;
    for (int i = 0; i < n; i++) {
        int c = t[i];
        while (!v->next[c]) {
            v = v->next[0];
        }
        v = v->next[c];
        if (v->accept != 110) { ret++; }
        matchs[y][i] = v->accept;
    }
    return ret;
}

void reverse(char p[1010][1010], int w, int h) {
    REP(y, h) {
        reverse(p[y], p[y] + w);
    }
}

char temp[1010][1010];
void rotate(char p[1010][1010], int w, int h) {
  memcpy(temp, p, sizeof(temp));
    REP(y, h) REP(x, w) {
        temp[x][y] = p[h - y - 1][x];
    }
    memcpy(p, temp, sizeof(temp));
}

int width, height, p;
char str[1010];
char imageData[1010][1010];
char pattern[1010][1010];
char iniPattern[1010][1010];
char mapto[1][1010];

char temp2[1010][1010];
int calc() {
    int ret = 0;
    REP(y, height) {
        match(imageData[y], width, root1, matchs, y);
    }
    rotate(matchs, width, height);
    REP(y, width) {
        ret += match(matchs[y], height, root2, temp2, y);
    }
    return ret;
}

int convert(char c) {
    if (isupper(c)) {
        return c - 'A';
    } else if (islower(c)) {
        return c - 'a' + 26;
    } else if (isdigit(c)) {
        return c - '0' + 52;
    } else if (c == '+') {
        return 62;
    } else if (c == '/') {
        return 63;
    }
    assert(false);
    return -1;
}

void input(char data[1010][1010], int w, int h) {
    REP(y, h) {
        scanf("%s", str);
        REP(x, (w + 5) / 6) {
            int value = convert(str[x]);
            REP(i, 6) {
                data[y][x * 6 + (5 - i)] = (value & 1) + 1;
                value >>= 1;
            }
        }
        data[y][w] = 0;
    }
}


int main() {
    freopen("H.in", "r", stdin);
    while (scanf("%d %d %d", &width, &height, &p), width|height|p) {
      MEMSET(matchs, 0);
      MEMSET(mapto, 0);
        MEMSET(temp, 0);
        MEMSET(imageData, 0);
        MEMSET(pattern, 0);
        input(imageData, width, height);
        input(pattern, p, p);
        //print(imageData, width, height);
        //print(pattern, p, p);
        REP(y, p) {
            char value = y;
            REP(i, y) {
                if (memcmp(pattern[y], pattern[i], sizeof(pattern[y]))  == 0) { value = i; break; }
            }
            mapto[0][y] = value + 1;
        }

        root1 = buildPMA(pattern, p);
        root2 = buildPMA(mapto, 1);

        ll ans = 0;
        REP(i, 2) {
            REP(j, 4) {
                //cout << i << " " << j << " " << width << " " << height << endl;
                //print(imageData, width, height);
                ans += calc();
                rotate(imageData, width, height);
                swap(width, height);
            }
            reverse(imageData, width, height);
        }
        bool lr = false;
        bool ud = false;
        bool mirror = false;
        bool r180 = false;
        memcpy(iniPattern, pattern, sizeof(pattern));
        reverse(pattern, p, p);

        if (memcmp(iniPattern, pattern, sizeof(pattern)) == 0) { lr = true;}
        rotate(pattern, p, p);
        if (memcmp(iniPattern, pattern, sizeof(pattern)) == 0) { mirror = true;}
        rotate(pattern, p, p);
        if (memcmp(iniPattern, pattern, sizeof(pattern)) == 0) { ud = true;}
        reverse(pattern, p, p);
        if (memcmp(iniPattern, pattern, sizeof(pattern)) == 0) { r180 = true;}
        reverse(pattern, p, p);
        rotate(pattern, p, p);
        if (memcmp(iniPattern, pattern, sizeof(pattern)) == 0) { mirror = true;}

        //cout << ans << endl;
        //cout << ud << " "  << lr << " " << mirror << " " << r180 << endl;
        if (ud && lr && mirror) {
            assert(ans % 8 == 0);
            assert(r180);
            ans /= 8;
        } else if (r180) {
            assert(ans % 4 == 0);
            //assert(!ud && !lr);
            ans /= 4;
        } else if ((ud || lr) && mirror) {
          assert(ans % 4 == 0);
          ans /= 4;
        } else if (ud || lr || mirror) {
            assert(ans % 2 == 0);
            assert(!r180);
            ans /= 2;
        }
        deletePMA(root1);
        deletePMA(root2);
        printf("%lld\n", ans);
    }
}

Compiler output:
a.cc: In function 'PMA* buildPMA(char (*)[1010], int)':
a.cc:57:5: error: 'queue' was not declared in this scope
   57 |     queue<PMA*> que;
      |     ^~~~~
a.cc:8:1: note: 'std::queue' is defined in header '<queue>'; this is probably fixable by adding '#include <queue>'
    7 | #include <vector>
  +++ |+#include <queue>
    8 | 
a.cc:57:14: error: expected primary-expression before '*' token
   57 |     queue<PMA*> que;
      |              ^
a.cc:57:15: error: expected primary-expression before '>' token
   57 |     queue<PMA*> que;
      |               ^
a.cc:57:17: error: 'que' was not declared in this scope
   57 |     queue<PMA*> que;
      |                 ^~~
a.cc: In function 'void deletePMA(PMA*)':
a.cc:89:5: error: 'set' was not declared in this scope
   89 |     set<PMA*> visit;
      |     ^~~
a.cc:8:1: note: 'std::set' is defined in header '<set>'; this is probably fixable by adding '#include <set>'
    7 | #include <vector>
  +++ |+#include <set>
    8 | 
a.cc:89:12: error: expected primary-expression before '*' token
   89 |     set<PMA*> visit;
      |            ^
a.cc:89:13: error: expected primary-expression before '>' token
   89 |     set<PMA*> visit;
      |             ^
a.cc:89:15: error: 'visit' was not declared in this scope
   89 |     set<PMA*> visit;
      |               ^~~~~
a.cc:8:1: note: 'std::visit' is defined in header '<variant>'; this is probably fixable by adding '#include <variant>'
    7 | #include <vector>
  +++ |+#include <variant>
    8 | 
a.cc:90:5: error: 'queue' was not declared in this scope
   90 |     queue<PMA*> que;
      |     ^~~~~
a.cc:90:5: note: 'std::queue' is defined in header '<queue>'; this is probably fixable by adding '#include <queue>'
a.cc:90:14: error: expected primary-expression before '*' token
   90 |     queue<PMA*> que;
      |              ^
a.cc:90:15: error: expected primary-expression before '>' token
   90 |     queue<PMA*> que;
      |               ^
a.cc:90:17: error: 'que' was not declared in this scope
   90 |     queue<PMA*> que;
      |                 ^~~
a.cc:103:31: error: invalid type argument of unary '*' (have 'int')
  103 |     FORIT(it, visit) { delete *it; }
      |                               ^~~