Problem p02913 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <bits/stdc++.h>
using namespace std;
/*{{{*/ // template
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define rrep(i, n) for (int i = (n)-1; i >= 0; i--)
constexpr int INF = numeric_limits<int>::max() / 2;
constexpr long long LINF = numeric_limits<long long>::max() / 3;
#define pb push_back
#define eb emplace_back
#define fi first
#define se second
#define all(v) (v).begin(), (v).end()
#define sz(x) (int)(x).size()
#define debug(x) cerr << #x << ":" << x << endl
#define debug2(x, y) cerr << #x << "," << #y ":" << x << "," << y << endl
// struct fin{ fin(){ cin.tie(0); ios::sync_with_stdio(false); } } fin_;
struct Double {
  double d;
  explicit Double(double x) : d(x) {}
};
ostream &operator<<(ostream &os, const Double x) {
  os << fixed << setprecision(20) << x.d;
  return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
  os << "[";
  for (const auto &v : vec) {
    os << v << ",";
  }
  os << "]";
  return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &mp) {
  os << "{";
  for (auto &p : mp) {
    os << p << ",";
  }
  os << "}";
  return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  os << "(" << p.first << "," << p.second << ")";
  return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &st) {
  os << "{";
  for (T v : st)
    os << v << ",";
  os << "}";
  return os;
}
template <typename T, typename U> inline void chmax(T &x, U y) {
  if (y > x)
    x = y;
}
template <typename T, typename U> inline void chmin(T &x, U y) {
  if (y < x)
    x = y;
}
using ll = long long;
using pii = std::pair<int, int>;
using vi = std::vector<int>;
typedef vector<vi> vvi;
ll gcd(ll a, ll b) {
  if (b == 0)
    return a;
  else
    return gcd(b, a % b);
}
constexpr ll TEN(int n) { return (n == 0) ? 1 : 10 * TEN(n - 1); }
// constexpr double eps = 1e-14;
constexpr double eps = 1e-10;
const int dx[] = {1, 0, -1, 0}, dy[] = {0, 1, 0, -1};
/*}}}*/

struct RollingHash {
  static const int hash_size = 2;
  vector<long long> mod{999999937LL, 1000000007LL};
  const long long base = 9973;
  vector<long long> pw[hash_size], hs[hash_size];
  RollingHash(const string &s) {
    int n = s.size();
    for (int i = 0; i < hash_size; i++) {
      pw[i].resize(n + 1);
      pw[i][0] = 1;
      for (int j = 0; j < n; j++)
        pw[i][j + 1] = pw[i][j] * base % mod[i];

      hs[i].resize(n + 1);
      hs[i][0] = 0;
      for (int j = 0; j < n; j++) {
        hs[i][j + 1] = hs[i][j] * base % mod[i] + s[j];
        if (hs[i][j + 1] >= mod[i])
          hs[i][j + 1] -= mod[i];
      }
    }
  }

  long long get(int l, int r, int i) const {
    long long ret = hs[i][r] + mod[i] - (hs[i][l] * pw[i][r - l] % mod[i]);
    if (ret >= mod[i])
      ret -= mod[i];
    return ret;
  }

  bool match(int l1, int r1, int l2, int r2) const {
    for (int i = 0; i < hash_size; i++) {
      if (get(l1, r1, i) != get(l2, r2, i))
        return false;
    }
    return true;
  }

  bool match(int l, int r, const RollingHash &p, int pl, int pr) const {
    for (int i = 0; i < hash_size; i++) {
      if (get(l, r, i) != p.get(pl, pr, i))
        return false;
    }
    return true;
  }
};

int n;
string s;

int main() {
  cin >> n >> s;

  RollingHash rh(s);

  int low = 0;
  int high = n;
  while (high - low > 1) {
    int m = (low + high) / 2;
    bool ok = false;
    for (int i = 0; i + m <= n; i++) {
      for (int j = i + m; j + m <= n; j++) {
        if (rh.match(i, i + m, j, j + m)) {
          ok = true;
          break;
        }
      }
      if (ok)
        break;
    }

    if (ok) {
      low = m;
    } else {
      high = m;
    }
  }
  cout << low << endl;
}


Fixed submission:
#include <bits/stdc++.h>
using namespace std;
/*{{{*/ // template
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define rrep(i, n) for (int i = (n)-1; i >= 0; i--)
constexpr int INF = numeric_limits<int>::max() / 2;
constexpr long long LINF = numeric_limits<long long>::max() / 3;
#define pb push_back
#define eb emplace_back
#define fi first
#define se second
#define all(v) (v).begin(), (v).end()
#define sz(x) (int)(x).size()
#define debug(x) cerr << #x << ":" << x << endl
#define debug2(x, y) cerr << #x << "," << #y ":" << x << "," << y << endl
// struct fin{ fin(){ cin.tie(0); ios::sync_with_stdio(false); } } fin_;
struct Double {
  double d;
  explicit Double(double x) : d(x) {}
};
ostream &operator<<(ostream &os, const Double x) {
  os << fixed << setprecision(20) << x.d;
  return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
  os << "[";
  for (const auto &v : vec) {
    os << v << ",";
  }
  os << "]";
  return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &mp) {
  os << "{";
  for (auto &p : mp) {
    os << p << ",";
  }
  os << "}";
  return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  os << "(" << p.first << "," << p.second << ")";
  return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &st) {
  os << "{";
  for (T v : st)
    os << v << ",";
  os << "}";
  return os;
}
template <typename T, typename U> inline void chmax(T &x, U y) {
  if (y > x)
    x = y;
}
template <typename T, typename U> inline void chmin(T &x, U y) {
  if (y < x)
    x = y;
}
using ll = long long;
using pii = std::pair<int, int>;
using vi = std::vector<int>;
typedef vector<vi> vvi;
ll gcd(ll a, ll b) {
  if (b == 0)
    return a;
  else
    return gcd(b, a % b);
}
constexpr ll TEN(int n) { return (n == 0) ? 1 : 10 * TEN(n - 1); }
// constexpr double eps = 1e-14;
constexpr double eps = 1e-10;
const int dx[] = {1, 0, -1, 0}, dy[] = {0, 1, 0, -1};
/*}}}*/

struct RollingHash {
  static const int hash_size = 2;
  vector<long long> mod{999999937LL, 1000000007LL};
  const long long base = 9973;
  vector<long long> pw[hash_size], hs[hash_size];
  RollingHash(const string &s) {
    int n = s.size();
    for (int i = 0; i < hash_size; i++) {
      pw[i].resize(n + 1);
      pw[i][0] = 1;
      for (int j = 0; j < n; j++)
        pw[i][j + 1] = pw[i][j] * base % mod[i];

      hs[i].resize(n + 1);
      hs[i][0] = 0;
      for (int j = 0; j < n; j++) {
        hs[i][j + 1] = hs[i][j] * base % mod[i] + s[j];
        if (hs[i][j + 1] >= mod[i])
          hs[i][j + 1] -= mod[i];
      }
    }
  }

  long long get(int l, int r, int i) const {
    long long ret = hs[i][r] + mod[i] - (hs[i][l] * pw[i][r - l] % mod[i]);
    if (ret >= mod[i])
      ret -= mod[i];
    return ret;
  }

  bool match(int l1, int r1, int l2, int r2) const {
    for (int i = 0; i < hash_size; i++) {
      if (get(l1, r1, i) != get(l2, r2, i))
        return false;
    }
    return true;
  }

  bool match(int l, int r, const RollingHash &p, int pl, int pr) const {
    for (int i = 0; i < hash_size; i++) {
      if (get(l, r, i) != p.get(pl, pr, i))
        return false;
    }
    return true;
  }
};

int n;
string s;

int main() {
  cin >> n >> s;

  RollingHash rh(s);

  int low = 0;
  int high = n;
  while (high - low > 1) {
    int m = (low + high) / 2;
    bool ok = false;
    for (int i = 0; i + m <= n; i++) {
      for (int j = i + m; j + m <= n; j++) {
        if (s[i] != s[j])
          continue;
        if (rh.match(i, i + m, j, j + m)) {
          ok = true;
          break;
        }
      }
      if (ok)
        break;
    }

    if (ok) {
      low = m;
    } else {
      high = m;
    }
  }
  cout << low << endl;
}