Problem p02913 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <algorithm>
#include <complex>
#include <cstdio>
#include <deque>
#include <iomanip>
#include <iostream>
#include <map>
#include <memory>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>

#define REP(i, m, n) for (int i = int(m); i < int(n); i++)
#define RREP(i, m, n) for (int i = int(n) - 1; i >= int(m); --i)
#define EACH(i, c) for (auto &(i) : c)
#define all(c) begin(c), end(c)
#define EXIST(s, e) ((s).find(e) != (s).end())
#define SORT(c) sort(begin(c), end(c))
#define pb emplace_back
#define MP make_pair
#define SZ(a) int((a).size())

#ifdef LOCAL
#define DEBUG(s) cout << (s) << endl
#define dump(x) cerr << #x << " = " << (x) << endl
#define BR cout << endl;
#else
#define DEBUG(s)                                                               \
  do {                                                                         \
  } while (0)
#define dump(x)                                                                \
  do {                                                                         \
  } while (0)
#define BR
#endif
using namespace std;

using UI = unsigned int;
using UL = unsigned long;
using LL = long long int;
using ULL = unsigned long long;
using VI = vector<int>;
using VVI = vector<VI>;
using VLL = vector<LL>;
using VVLL = vector<VLL>;
using VS = vector<string>;
using PII = pair<int, int>;
using VP = vector<PII>;

const int MAX = 500000, MS = 2;
const long long mod[] = {999999937LL, 1000000007LL}, base = 9973;

struct rolling_hash {
  int n;
  vector<long long> hs[MS], pw[MS];
  rolling_hash() {}
  rolling_hash(const string &s) {
    n = s.size();
    for (int i = 0; i < MS; i++) {
      hs[i].assign(n + 1, 0);
      pw[i].assign(n + 1, 0);
      hs[i][0] = 0;
      pw[i][0] = 1;
      for (int j = 0; j < n; j++) {
        pw[i][j + 1] = pw[i][j] * base % mod[i];
        hs[i][j + 1] = (hs[i][j] * base + s[j]) % mod[i];
      }
    }
  }

  long long hash(int l, int r, int i) {
    return ((hs[i][r] - hs[i][l] * pw[i][r - l]) % mod[i] + mod[i]) % mod[i];
  }

  bool match(int l1, int r1, int l2, int r2) {
    bool ret = 1;
    for (int i = 0; i < MS; i++)
      ret &= hash(l1, r1, i) == hash(l2, r2, i);
    return ret;
  }
};

bool solve(int &len, rolling_hash &rh, int &n, string &s) {
  // dump(len);
  REP(i, 0, n - len + 1) REP(j, i + len, n - len + 1) {
    // cerr << i << ", " << j << endl;
    if (rh.match(i, i + len, j, j + len))
      return true;
  }
  return false;
};

int meguru_bin(rolling_hash &rh, int &n, string &s) {
  int ng = n + 1;
  int ok = -1;

  while (abs(ok - ng) > 1) {
    int mid = ng + (ok - ng) / 2;
    // cerr << ok << ", " << ng << ", " << mid << endl;
    if (solve(mid, rh, n, s))
      ok = mid;
    else
      ng = mid;
  }

  return ok;
}

void solve() {
  int n;
  string s;
  cin >> n >> s;
  rolling_hash rh(s);
  cout << meguru_bin(rh, n, s) << endl;
}

int main() {
  solve();

  return 0;
}

Fixed submission:
#include <algorithm>
#include <complex>
#include <cstdio>
#include <deque>
#include <iomanip>
#include <iostream>
#include <map>
#include <memory>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>

#define REP(i, m, n) for (int i = int(m); i < int(n); i++)
#define RREP(i, m, n) for (int i = int(n) - 1; i >= int(m); --i)
#define EACH(i, c) for (auto &(i) : c)
#define all(c) begin(c), end(c)
#define EXIST(s, e) ((s).find(e) != (s).end())
#define SORT(c) sort(begin(c), end(c))
#define pb emplace_back
#define MP make_pair
#define SZ(a) int((a).size())

#ifdef LOCAL
#define DEBUG(s) cout << (s) << endl
#define dump(x) cerr << #x << " = " << (x) << endl
#define BR cout << endl;
#else
#define DEBUG(s)                                                               \
  do {                                                                         \
  } while (0)
#define dump(x)                                                                \
  do {                                                                         \
  } while (0)
#define BR
#endif
using namespace std;

using UI = unsigned int;
using UL = unsigned long;
using LL = long long int;
using ULL = unsigned long long;
using VI = vector<int>;
using VVI = vector<VI>;
using VLL = vector<LL>;
using VVLL = vector<VLL>;
using VS = vector<string>;
using PII = pair<int, int>;
using VP = vector<PII>;

const int MAX = 500000, MS = 2;
const long long mod[] = {999999937LL, 1000000007LL}, base = 9973;

struct rolling_hash {
  int n;
  vector<long long> hs[MS], pw[MS];
  rolling_hash() {}
  rolling_hash(const string &s) {
    n = s.size();
    for (int i = 0; i < MS; i++) {
      hs[i].assign(n + 1, 0);
      pw[i].assign(n + 1, 0);
      hs[i][0] = 0;
      pw[i][0] = 1;
      for (int j = 0; j < n; j++) {
        pw[i][j + 1] = pw[i][j] * base % mod[i];
        hs[i][j + 1] = (hs[i][j] * base + s[j]) % mod[i];
      }
    }
  }

  long long hash(int l, int r, int i) {
    return ((hs[i][r] - hs[i][l] * pw[i][r - l]) % mod[i] + mod[i]) % mod[i];
  }

  bool match(int l1, int r1, int l2, int r2) {
    bool ret = 1;
    for (int i = 0; i < MS; i++)
      ret &= hash(l1, r1, i) == hash(l2, r2, i);
    return ret;
  }
};

bool solve(int &len, rolling_hash &rh, int &n, string &s) {
  // dump(len);
  /*
  REP(i,0,n-len+1) REP(j,i+len,n-len+1) {
      //cerr << i << ", " << j << endl;
      if (rh.match(i,i+len,j,j+len)) return true;
  }
  */
  vector<map<LL, int>> se(2);
  REP(i, 0, n - len + 1) {
    LL hash1 = rh.hash(i, i + len, 0), hash2 = rh.hash(i, i + len, 1);
    /*
    if (len == 3) {
        dump(hash1);
        dump(hash2);
    }
    */
    if (se[0].count(hash1) > 0 && se[1].count(hash2) > 0) {
      if (se[0][hash1] == se[1][hash2]) {
        if (se[0][hash1] + len <= i)
          return true;
        else
          continue;
      }
    }
    se[0].emplace(hash1, i);
    se[1].emplace(hash2, i);
  }
  return false;
};

int meguru_bin(rolling_hash &rh, int &n, string &s) {
  int ng = n + 1;
  int ok = -1;

  while (abs(ok - ng) > 1) {
    int mid = ng + (ok - ng) / 2;
    // cerr << ok << ", " << ng << ", " << mid << endl;
    if (solve(mid, rh, n, s))
      ok = mid;
    else
      ng = mid;
  }

  return ok;
}

void solve() {
  int n;
  string s;
  cin >> n >> s;
  rolling_hash rh(s);
  cout << meguru_bin(rh, n, s) << endl;
}

int main() {
  solve();

  return 0;
}