Problem p02913 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#define _USE_MATH_DEFINES
#include <cmath>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iostream>
#include <iterator>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <tuple>
#include <utility>
#include <vector>
using namespace std;

#define FOR(i, m, n) for (int i = (m); i < (n); ++i)
#define REP(i, n) FOR(i, 0, n)
#define ALL(v) (v).begin(), (v).end()

const int INF = 0x3f3f3f3f;
const long long LINF = 0x3f3f3f3f3f3f3f3fLL;
const double EPS = 1e-8;
const int MOD = 1000000007; // 998244353;
const int dy[] = {1, 0, -1, 0}, dx[] = {0, -1, 0, 1};
/*-------------------------------------------------*/
template <typename T = string> struct RollingHash {
  T str;

  RollingHash(const T &s, int base = 10007, int mod = 1000000007)
      : str(s), base(base), mod(mod) {
    int n = str.size();
    hash_val.resize(n + 1);
    hash_val[0] = 0;
    power.resize(n + 1);
    power[0] = 1;
    REP(i, n) {
      hash_val[i + 1] = (hash_val[i] * base % mod + str[i]) % mod;
      power[i + 1] = power[i] * base % mod;
    }
  }

  long long get(int left, int right) {
    long long res =
        hash_val[right] - hash_val[left] * power[right - left] % mod;
    if (res < 0)
      res += mod;
    return res;
  }

  void add(const T &t) {
    for (auto c : t) {
      hash_val.emplace_back((hash_val.back() * base % mod + c) % mod);
      power.emplace_back(power.back() * base % mod);
    }
  }

  int lcp(int i, int j) {
    int n = str.size(), lb = 0, ub = n + 1 - max(i, j);
    while (ub - lb > 1) {
      int mid = (lb + ub) >> 1;
      (get(i, i + mid) == get(j, j + mid) ? lb : ub) = mid;
    }
    return lb;
  }

  template <typename U> int lcp(const RollingHash<U> &t, int i, int j) {
    int lb = 0, ub = min(static_cast<int>(str.size()) - i,
                         static_cast<int>(t.str.size()) - j) +
                     1;
    while (ub - lb > 1) {
      int mid = (lb + ub) >> 1;
      (get(i, i + mid) == t.get(j, j + mid) ? lb : ub) = mid;
    }
    return lb;
  }

private:
  int base, mod;
  vector<long long> hash_val, power;
};

int main() {
  cin.tie(nullptr);
  ios::sync_with_stdio(false);
  // freopen("input.txt", "r", stdin);

  int n;
  cin >> n;
  string s;
  cin >> s;
  RollingHash<> rh(s);
  int ans = 0;
  REP(i, n) FOR(j, i + 1, n) ans = max(ans, min(rh.lcp(i, j), j - i));
  cout << ans << '\n';
  return 0;
}


Fixed submission:
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#define _USE_MATH_DEFINES
#include <cmath>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iostream>
#include <iterator>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <tuple>
#include <utility>
#include <vector>
using namespace std;

#define FOR(i, m, n) for (int i = (m); i < (n); ++i)
#define REP(i, n) FOR(i, 0, n)
#define ALL(v) (v).begin(), (v).end()

const int INF = 0x3f3f3f3f;
const long long LINF = 0x3f3f3f3f3f3f3f3fLL;
const double EPS = 1e-8;
const int MOD = 1000000007; // 998244353;
const int dy[] = {1, 0, -1, 0}, dx[] = {0, -1, 0, 1};
/*-------------------------------------------------*/
template <typename T = string> struct RollingHash {
  T str;

  RollingHash(const T &s, int base = 10007, int mod = 1000000007)
      : str(s), base(base), mod(mod) {
    int n = str.size();
    hash_val.resize(n + 1);
    hash_val[0] = 0;
    power.resize(n + 1);
    power[0] = 1;
    REP(i, n) {
      hash_val[i + 1] = (hash_val[i] * base % mod + str[i]) % mod;
      power[i + 1] = power[i] * base % mod;
    }
  }

  long long get(int left, int right) {
    long long res =
        hash_val[right] - hash_val[left] * power[right - left] % mod;
    if (res < 0)
      res += mod;
    return res;
  }

  void add(const T &t) {
    for (auto c : t) {
      hash_val.emplace_back((hash_val.back() * base % mod + c) % mod);
      power.emplace_back(power.back() * base % mod);
    }
  }

  int lcp(int i, int j) {
    int n = str.size(), lb = 0, ub = n + 1 - max(i, j);
    while (ub - lb > 1) {
      int mid = (lb + ub) >> 1;
      (get(i, i + mid) == get(j, j + mid) ? lb : ub) = mid;
    }
    return lb;
  }

  template <typename U> int lcp(const RollingHash<U> &t, int i, int j) {
    int lb = 0, ub = min(static_cast<int>(str.size()) - i,
                         static_cast<int>(t.str.size()) - j) +
                     1;
    while (ub - lb > 1) {
      int mid = (lb + ub) >> 1;
      (get(i, i + mid) == t.get(j, j + mid) ? lb : ub) = mid;
    }
    return lb;
  }

private:
  int base, mod;
  vector<long long> hash_val, power;
};

int main() {
  cin.tie(nullptr);
  ios::sync_with_stdio(false);
  // freopen("input.txt", "r", stdin);

  int n;
  cin >> n;
  string s;
  cin >> s;
  RollingHash<> rh(s);
  int lb = 0, ub = n + 1;
  while (ub - lb > 1) {
    int mid = (lb + ub) / 2;
    map<long long, vector<int>> mp;
    REP(i, n) {
      if (i + mid > n)
        break;
      mp[rh.get(i, i + mid)].emplace_back(i);
    }
    bool ok = false;
    for (auto pr : mp) {
      if (pr.second.size() >= 2) {
        if (pr.second.back() - pr.second.front() >= mid)
          ok = true;
      }
    }
    (ok ? lb : ub) = mid;
  }
  cout << lb << '\n';
  return 0;
}