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

#include "bits/stdc++.h"
#include <unordered_map>
#include <unordered_set>
#pragma warning(disable : 4996)
using namespace std;
using ld = long double;
template <class T> using Table = vector<vector<T>>;
const ld eps = 1e-9;

// < "D:\\D_Download\\Visual Studio
// 2015\\Projects\\programing_contest_c++\\Debug\\a.txt" > "D:\\D_Download\\Visual
// Studio 2015\\Projects\\programing_contest_c++\\Debug\\b.answer"

using ll = long long int;
using ha = pair<int, int>;
struct RollingHash {
  static const ll mul0 = 10009, mul1 = 10007;
  static const ll add0 = 1000010007, add1 = 1003333331;
  size_t len;
  // vector<ll> hash_, hash2_;
  vector<ha> hash_;
  // static vector<ll> pmo_, pmo2_;
  static vector<ha> pmo_;
  void init(const vector<ll> &s) {
    len = s.size();
    hash_.resize(len + 1);
    hash_[0] = make_pair(0, 0);

    if (pmo_.empty()) {
      pmo_.push_back(make_pair(1, 1));
    }
    while (pmo_.size() <= len) {
      pmo_.push_back(
          make_pair(pmo_.back().first * mul0, pmo_.back().second * mul1));
    }
    for (unsigned int i = 0; i < len; ++i) {
      hash_[i + 1] = make_pair((hash_[i].first * mul0 + s[i]),
                               (hash_[i].second * mul1 + s[i]));
    }
    return;
  }
  void init(const string &s) {
    vector<ll> v;
    for (char c : s) {
      v.push_back(c);
    }
    init(v);
  }
  ha hash(const int l, const int r) const { // s[l..r]
    return make_pair(
        hash_[r + 1].first - hash_[l].first * pmo_[r + 1 - l].first,
        hash_[r + 1].second - hash_[l].second * pmo_[r + 1 - l].second);
  }
  ha hash() const { // s[all]
    return hash(0, len - 1);
  }

  // hash????????????
  static ha concat(const ha L, const ha R, const int RLength) { // hash(L+R)
    return make_pair((R.first + L.first * pmo_[RLength].first),
                     (R.second + L.second * pmo_[RLength].second));
  }

  // index????????????from??????to????????????????????????????????\\????????????
  ha get_changed_hash(const int index, const ll from, const ll to) const {
    const ha p(hash());
    return make_pair(p.first + (to - from) * pmo_[len - index - 1].first,
                     p.second + (to - from) * pmo_[len - index - 1].second);
  }
};
vector<ha> RollingHash::pmo_;

int main() {
  string s, t;
  cin >> s >> t;
  RollingHash base_rh;
  base_rh.init(t);
  vector<ha> hs;
  for (int i = 0; i < t.size(); ++i) {
    for (int c = 0; c < 26; ++c) {
      char ch = 'a' + c;
      if (ch == t[i])
        continue;
      else {
        ha ahash = base_rh.get_changed_hash(i, t[i], ch);
        hs.emplace_back(ahash);
      }
    }
    for (int c = 0; c < 26; ++c) {
      char ch = 'A' + c;
      if (ch == t[i])
        continue;
      else {
        ha ahash = base_rh.get_changed_hash(i, t[i], ch);
        hs.emplace_back(ahash);
      }
    }
  }
  sort(hs.begin(), hs.end());
  hs.erase(unique(hs.begin(), hs.end()), hs.end());
  RollingHash s_rh;
  s_rh.init(s);
  long long int ans = 0;
  for (int i = 0; i < s.size() - t.size() + 1; ++i) {
    ha h = s_rh.hash(i, i + t.size() - 1);
    if (binary_search(hs.begin(), hs.end(), h)) {
      ans++;
    }
  }
  cout << ans << endl;
  return 0;
}

Error: MLE

Fixed submission:

#include "bits/stdc++.h"
#include <unordered_map>
#include <unordered_set>
#pragma warning(disable : 4996)
using namespace std;
using ld = long double;
template <class T> using Table = vector<vector<T>>;
const ld eps = 1e-9;

// < "D:\\D_Download\\Visual Studio
// 2015\\Projects\\programing_contest_c++\\Debug\\a.txt" > "D:\\D_Download\\Visual
// Studio 2015\\Projects\\programing_contest_c++\\Debug\\b.answer"

using ll = long long int;
using ha = pair<ll, int>;
struct RollingHash {
  static const ll mul0 = 10009, mul1 = 10007;
  static const ll add0 = 1000010007, add1 = 1003333331;
  size_t len;
  // vector<ll> hash_, hash2_;
  vector<ha> hash_;
  // static vector<ll> pmo_, pmo2_;
  static vector<ha> pmo_;
  void init(const vector<ll> &s) {
    len = s.size();
    hash_.resize(len + 1);
    hash_[0] = make_pair(0, 0);

    if (pmo_.empty()) {
      pmo_.push_back(make_pair(1, 1));
    }
    while (pmo_.size() <= len) {
      pmo_.push_back(
          make_pair(pmo_.back().first * mul0, pmo_.back().second * mul1));
    }
    for (unsigned int i = 0; i < len; ++i) {
      hash_[i + 1] = make_pair((hash_[i].first * mul0 + s[i]),
                               (hash_[i].second * mul1 + s[i]));
    }
    return;
  }
  void init(const string &s) {
    vector<ll> v;
    for (char c : s) {
      v.push_back(c);
    }
    init(v);
  }
  ha hash(const int l, const int r) const { // s[l..r]
    return make_pair(
        hash_[r + 1].first - hash_[l].first * pmo_[r + 1 - l].first,
        hash_[r + 1].second - hash_[l].second * pmo_[r + 1 - l].second);
  }
  ha hash() const { // s[all]
    return hash(0, len - 1);
  }

  // hash????????????
  static ha concat(const ha L, const ha R, const int RLength) { // hash(L+R)
    return make_pair((R.first + L.first * pmo_[RLength].first),
                     (R.second + L.second * pmo_[RLength].second));
  }

  // index????????????from??????to????????????????????????????????\\????????????
  ha get_changed_hash(const int index, const ll from, const ll to) const {
    const ha p(hash());
    return make_pair(p.first + (to - from) * pmo_[len - index - 1].first,
                     p.second + (to - from) * pmo_[len - index - 1].second);
  }
};
vector<ha> RollingHash::pmo_;

int main() {
  string s, t;
  cin >> s >> t;
  RollingHash base_rh;
  base_rh.init(t);
  vector<ha> hs;
  for (int i = 0; i < t.size(); ++i) {
    for (int c = 0; c < 26; ++c) {
      char ch = 'a' + c;
      if (ch == t[i])
        continue;
      else {
        ha ahash = base_rh.get_changed_hash(i, t[i], ch);
        hs.emplace_back(ahash);
      }
    }
    for (int c = 0; c < 26; ++c) {
      char ch = 'A' + c;
      if (ch == t[i])
        continue;
      else {
        ha ahash = base_rh.get_changed_hash(i, t[i], ch);
        hs.emplace_back(ahash);
      }
    }
  }
  sort(hs.begin(), hs.end());
  hs.erase(unique(hs.begin(), hs.end()), hs.end());
  RollingHash s_rh;
  s_rh.init(s);
  long long int ans = 0;
  for (int i = 0; i < s.size() - t.size() + 1; ++i) {
    ha h = s_rh.hash(i, i + t.size() - 1);
    if (binary_search(hs.begin(), hs.end(), h)) {
      ans++;
    }
  }
  cout << ans << endl;
  return 0;
}