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

#include <algorithm>
#include <array>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <valarray>
#include <vector>

using namespace std;
using ll = long long;
using ull = unsigned long long;
constexpr int TEN(int n) { return (n == 0) ? 1 : 10 * TEN(n - 1); }

/// x^n
template <class T> T pow(T x, ll n) {
  T r = 1;
  while (n) {
    if (n & 1)
      r *= x;
    x *= x;
    n >>= 1;
  }
  return r;
}

template <uint MD> struct ModInt {
  uint v;
  ModInt() : v(0) {}
  ModInt(ll v) : v(normS(v % MD + MD)) {}
  uint value() { return v; }
  static uint normS(const uint &x) { return (x < MD) ? x : x - MD; };
  static ModInt make(const uint &x) {
    ModInt m;
    m.v = x;
    return m;
  }
  const ModInt operator+(const ModInt &r) const { return make(normS(v + r.v)); }
  const ModInt operator-(const ModInt &r) const {
    return make(normS(v + normS(MD - r.v)));
  }
  const ModInt operator*(const ModInt &r) const {
    return make((ull)v * r.v % MD);
  }
  ModInt &operator+=(const ModInt &r) { return *this = *this + r; }
  ModInt &operator-=(const ModInt &r) { return *this = *this - r; }
  ModInt &operator*=(const ModInt &r) { return *this = *this * r; }
  static ModInt inv(const ModInt &x) { return pow(ModInt(x), MD - 2); }
};

const int MN = 300300;

int n, m;
bool ok[MN];
int s[MN], t[MN];
template <uint B, uint MD> struct Checker {
  using Mint = ModInt<MD>;
  Mint powB[MN], invB[MN], iB;
  Mint invJ[102 + 1];
  void init() {
    powB[0] = 1;
    for (int i = 1; i < MN; i++) {
      powB[i] = powB[i - 1] * B;
    }
    for (int i = 0; i < MN; i++) {
      invB[i] = Mint::inv(powB[i]);
    }
    iB = Mint::inv(B);
  }
  void check() {
    Mint hs = 0, HS = 0;
    unordered_set<uint> stB;
    for (int i = 0; i < m; i++) {
      HS += powB[i] * t[i];
      stB.insert(powB[i].v);
    }
    for (int i = -51; i <= 51; i++) {
      invJ[i + 51] = Mint::inv(Mint(i));
    }
    for (int i = 0; i < m - 1; i++) {
      hs += powB[i] * s[i];
    }

    for (int i = 0; i <= n - m; i++) {
      hs += powB[m - 1] * s[i + m - 1];
      Mint dif = hs - HS; // (-26 ~ 26) * powB[j]
      if (ok[i]) {
        bool f = false;
        for (int j = -51; j <= 51; j++) {
          if (j == 0)
            continue;
          if (stB.count((dif * invJ[j + 51]).v)) {
            f = true;
            break;
          }
        }
        if (!f) {
          ok[i] = false;
        }
      }
      hs -= s[i];
      hs *= iB;
    }
  }
};

int main() {
  string ss, tt;
  cin >> ss >> tt;
  n = (int)ss.size();
  m = (int)tt.size();
  for (int i = 0; i < n; i++) {
    if (islower(ss[i])) {
      s[i] = ss[i] - 'a';
    } else {
      s[i] = ss[i] - 'A' + 26;
    }
  }
  for (int i = 0; i < m; i++) {
    if (islower(tt[i])) {
      t[i] = tt[i] - 'a';
    } else {
      t[i] = tt[i] - 'A' + 26;
    }
  }
  fill_n(ok, n - m + 1, true);
  {
    constexpr uint B = 134987334, MD = 1e9 + 7;
    Checker<B, MD> chk;
    chk.init();
    chk.check();
  }
  {
    constexpr uint B = 592873984, MD = 1e9 + 9;
    Checker<B, MD> chk;
    chk.init();
    chk.check();
  }
  {
    constexpr uint B = 98754277, MD = 1e9 + 21;
    Checker<B, MD> chk;
    chk.init();
    chk.check();
  }
  {
    constexpr uint B = 958327444, MD = 1e9 + 33;
    Checker<B, MD> chk;
    chk.init();
    chk.check();
  }
  int ans = 0;
  for (int i = 0; i <= n - m; i++) {
    if (ok[i])
      ans++;
  }
  printf("%d\\n", ans);
  return 0;
}

Error: MLE

Fixed submission:

#include <algorithm>
#include <array>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <valarray>
#include <vector>

using namespace std;
using ll = long long;
using ull = unsigned long long;
constexpr int TEN(int n) { return (n == 0) ? 1 : 10 * TEN(n - 1); }

/// x^n
template <class T> T pow(T x, ll n) {
  T r = 1;
  while (n) {
    if (n & 1)
      r *= x;
    x *= x;
    n >>= 1;
  }
  return r;
}

template <uint MD> struct ModInt {
  uint v;
  ModInt() : v(0) {}
  ModInt(ll v) : v(normS(v % MD + MD)) {}
  uint value() { return v; }
  static uint normS(const uint &x) { return (x < MD) ? x : x - MD; };
  static ModInt make(const uint &x) {
    ModInt m;
    m.v = x;
    return m;
  }
  const ModInt operator+(const ModInt &r) const { return make(normS(v + r.v)); }
  const ModInt operator-(const ModInt &r) const {
    return make(normS(v + normS(MD - r.v)));
  }
  const ModInt operator*(const ModInt &r) const {
    return make((ull)v * r.v % MD);
  }
  ModInt &operator+=(const ModInt &r) { return *this = *this + r; }
  ModInt &operator-=(const ModInt &r) { return *this = *this - r; }
  ModInt &operator*=(const ModInt &r) { return *this = *this * r; }
  static ModInt inv(const ModInt &x) { return pow(ModInt(x), MD - 2); }
};

const int MN = 300300;

int n, m;
bool ok[MN];
string s, t;

template <uint B, uint MD> struct Checker {
  using Mint = ModInt<MD>;
  Mint powB[MN], invB[MN], iB;
  void init() {
    powB[0] = 1;
    for (int i = 1; i < MN; i++) {
      powB[i] = powB[i - 1] * B;
    }
    for (int i = 0; i < MN; i++) {
      invB[i] = Mint::inv(powB[i]);
    }
    iB = Mint::inv(B);
  }
  void check() {
    Mint hs = 0, HS = 0;
    unordered_set<uint> stB;
    for (int i = 0; i < m; i++) {
      HS += powB[i] * t[i];
      for (int j = -26; j <= 26; j++) {
        if (j == 0)
          continue;
        stB.insert((powB[i] * j).v);
        //                printf("%d %d %d\\n", i, j, (powB[i] * j).v);
      }
    }

    for (int i = 0; i < m - 1; i++) {
      hs += powB[i] * s[i];
    }

    for (int i = 0; i <= n - m; i++) {
      hs += powB[m - 1] * s[i + m - 1];
      Mint dif = hs - HS; // (-26 ~ 26) * powB[j]
                          //            printf("%d %d\\n", i, dif.v);
      if (!stB.count((hs - HS).v)) {
        ok[i] = false;
      }
      hs -= s[i];
      hs *= iB;
    }
  }
};

int main() {
  cin >> s >> t;
  n = (int)s.size();
  m = (int)t.size();
  fill_n(ok, n - m + 1, true);

  constexpr uint B = 134987334, MD = 1e9 + 7;
  Checker<B, MD> chk;
  chk.init();
  chk.check();
  int ans = 0;
  for (int i = 0; i <= n - m; i++) {
    if (ok[i])
      ans++;
    //        printf("%d, ", ok[i]);
  }
  //    printf("\\n");
  printf("%d\\n", ans);
  return 0;
}