Problem p01863 (C++)

Buggy submission (status: Runtime Error):
#include "bits/stdc++.h"
#include <unordered_map>
#include <unordered_set>
#pragma warning(disable : 4996)
using namespace std;
using ld = long double;
const ld eps = 1e-9;

using ll = long long int;
using ha = pair<ll, ll>;
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 st;
  cin >> st;
  RollingHash rh;
  rh.init(st);
  pair<int, int> ans = make_pair(0, 0);
  for (int a = st.size() / 3; a > 0; --a) {
    if ((st.size() - a * 3) % 2)
      continue;
    else {
      int b = (st.size() - a * 3) / 2;
      ha h0 = rh.hash(0, a - 1);
      ha h1 = rh.hash(a, a + b - 1);
      ha h2 = rh.hash(a + b, 2 * a + b - 1);
      ha h3 = rh.hash(2 * a + b, 2 * a + 2 * b - 1);
      ha h4 = rh.hash(2 * a + 2 * b, 3 * a + 2 * b - 1);
      if (h0 == h2 && h2 == h4 && h1 == h3) {
        ans = make_pair(a, b);
        break;
      }
    }
  }
  if (ans.first) {
    assert(ans.second);
    cout << "Love " << st.substr(0, ans.first)
         << st.substr(ans.first, ans.second) << "!" << endl;
  } else {
    cout << "mitomerarenaiWA" << endl;
  }
  return 0;
}

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

using ll = long long int;
using ha = pair<ll, ll>;
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 st;
  cin >> st;
  RollingHash rh;
  rh.init(st);
  pair<int, int> ans = make_pair(0, 0);
  for (int a = st.size() / 3; a > 0; --a) {
    if ((st.size() - a * 3) % 2)
      continue;
    else {
      int b = (st.size() - a * 3) / 2;
      if (b) {
        ha h0 = rh.hash(0, a - 1);
        ha h1 = rh.hash(a, a + b - 1);
        ha h2 = rh.hash(a + b, 2 * a + b - 1);
        ha h3 = rh.hash(2 * a + b, 2 * a + 2 * b - 1);
        ha h4 = rh.hash(2 * a + 2 * b, 3 * a + 2 * b - 1);
        if (h0 == h2 && h2 == h4 && h1 == h3) {
          ans = make_pair(a, b);
          break;
        }
      }
    }
  }
  if (ans.first) {
    assert(ans.second);
    cout << "Love " << st.substr(0, ans.first)
         << st.substr(ans.first, ans.second) << "!" << endl;
  } else {
    cout << "mitomerarenaiWA" << endl;
  }
  return 0;
}