Problem p00317 (C++)

Buggy submission (status: Memory Limit Exceeded):
#include <bits/stdc++.h>
using namespace std;

#define INF_LL (int64)1e18
#define INF (int32)1e9
#define REP(i, n) for (int64 i = 0; i < (n); i++)
#define FOR(i, a, b) for (int64 i = (a); i < (b); i++)
#define all(x) x.begin(), x.end()
#define fs first
#define sc second

using int32 = int_fast32_t;
using uint32 = uint_fast32_t;
using int64 = int_fast64_t;
using uint64 = uint_fast64_t;
using PII = pair<int32, int32>;
using PLL = pair<int64, int64>;

const double eps = 1e-10;

template <typename A, typename B> inline void chmin(A &a, B b) {
  if (a > b)
    a = b;
}
template <typename A, typename B> inline void chmax(A &a, B b) {
  if (a < b)
    a = b;
}

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]; }
};

map<uint64, int32> mpf, mpb, mp; // 前が欠けてる，後ろが欠けてる, 欠けてない
RollingHash r;
int main(void) {
  int32 N, M;
  cin >> N >> M;

  REP(i, N) {
    string s;
    cin >> s;
    r = RollingHash(s);
    mp[r.find(0, s.size())]++;
    FOR(j, 1, s.size()) {
      mpf[r.find(j, s.size())]++;
      mpb[r.find(0, j)]++;
    }
  }
  REP(i, M) {
    string s;
    cin >> s;
    int32 cq = -1, ca = -1;
    REP(j, s.size()) {
      if (s[j] == '?')
        cq = j;
      if (s[j] == '*')
        ca = j;
    }
    int32 res = 0;
    for (char c = 'a'; c <= 'z'; c++) {
      if (cq != -1)
        s[cq] = c;
      r = RollingHash(s);
      if (ca == -1) {
        res += mp[r.find(0, s.size())];
      } else if (ca == 0) {
        res += mpf[r.find(1, s.size())];
        res += mp[r.find(1, s.size())];
      } else {
        res += mpb[r.find(0, s.size() - 1)];
        res += mp[r.find(0, s.size() - 1)];
      }
      if (cq == -1)
        break;
    }
    cout << res << endl;
  }
}


Fixed submission:
#include <bits/stdc++.h>
using namespace std;

#define INF_LL (int64)1e18
#define INF (int32)1e9
#define REP(i, n) for (int64 i = 0; i < (n); i++)
#define FOR(i, a, b) for (int64 i = (a); i < (b); i++)
#define all(x) x.begin(), x.end()
#define fs first
#define sc second

using int32 = int_fast32_t;
using uint32 = uint_fast32_t;
using int64 = int_fast64_t;
using uint64 = uint_fast64_t;
using PII = pair<int32, int32>;
using PLL = pair<int64, int64>;

const double eps = 1e-10;

template <typename A, typename B> inline void chmin(A &a, B b) {
  if (a > b)
    a = b;
}
template <typename A, typename B> inline void chmax(A &a, B b) {
  if (a < b)
    a = b;
}

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]; }
};

unordered_map<uint64, int32> mpf, mpb,
    mp; // 前が欠けてる，後ろが欠けてる, 欠けてない
RollingHash r;
int main(void) {
  int32 N, M;
  cin >> N >> M;

  REP(i, N) {
    string s;
    cin >> s;
    r = RollingHash(s);
    mp[r.find(0, s.size())]++;
    FOR(j, 1, s.size()) {
      mpf[r.find(j, s.size())]++;
      mpb[r.find(0, j)]++;
    }
  }
  REP(i, M) {
    string s;
    cin >> s;
    int32 cq = -1, ca = -1;
    REP(j, s.size()) {
      if (s[j] == '?')
        cq = j;
      if (s[j] == '*')
        ca = j;
    }
    int32 res = 0;
    for (char c = 'a'; c <= 'z'; c++) {
      if (cq != -1)
        s[cq] = c;
      r = RollingHash(s);
      if (ca == -1) {
        res += mp[r.find(0, s.size())];
      } else if (ca == 0) {
        res += mpf[r.find(1, s.size())];
        res += mp[r.find(1, s.size())];
      } else {
        res += mpb[r.find(0, s.size() - 1)];
        res += mp[r.find(0, s.size() - 1)];
      }
      if (cq == -1)
        break;
    }
    cout << res << endl;
  }
}