Problem p02913 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <bits/stdc++.h>
using namespace std;
#define Rep(i, n) for (int i = 0; i < (int)(n); i++)
#define For(i, n1, n2) for (int i = (int)(n1); i < (int)(n2); i++)
#define REP(i, n) for (ll i = 0; i < (ll)(n); i++)
#define RREP(i, n) for (ll i = ((ll)(n)-1); i >= 0; i--)
#define FOR(i, n1, n2) for (ll i = (ll)(n1); i < (ll)(n2); i++)
#define RFOR(i, n1, n2) for (ll i = ((ll)(n1)-1); i >= (ll)(n2); i--)
#define all(a) (a).begin(), (a).end()
#define SORT(a) sort((a).begin(), (a).end())
#define oorret 0
#define oor(x)                                                                 \
  [&]() {                                                                      \
    try {                                                                      \
      x;                                                                       \
    } catch (const out_of_range &oor) {                                        \
      return oorret;                                                           \
    }                                                                          \
    return x;                                                                  \
  }()
#define IOS cin.tie(0), ios::sync_with_stdio(false)
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> P;
template <typename T1, typename T2> inline bool chmin(T1 &a, T2 b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
template <typename T1, typename T2> inline bool chmax(T1 &a, T2 b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class Type> struct is_vector : std::false_type {};
template <class ValueType, class Alloc>
struct is_vector<std::vector<ValueType, Alloc>> : std::true_type {};
template <typename T>
inline ostream &operator<<(ostream &out, const vector<T> &v) {
  if (v.empty())
    return out;
  constexpr bool is_vector_v = is_vector<T>::value;
  if (is_vector_v)
    for (auto itr = v.begin(); itr != v.end();)
      out << (*itr), out << ((++itr != v.end()) ? "\n" : "");
  else
    for (auto itr = v.begin(); itr != v.end();)
      out << (*itr), out << ((++itr != v.end()) ? " " : "");
  return out;
}
inline void put() {}
template <class T> inline void put(const T &first) {
  std::cout << first << "\n";
}
template <class T, class... N>
inline void put(const T &first, const N &...rest) {
  std::cout << first << " ";
  put(rest...);
}
inline void putn() {}
template <class T, class... N>
inline void putn(const T &first, const N &...rest) {
  std::cout << first << "\n";
  putn(rest...);
}

class RollingHash {
private:
  const ull base;
  const vector<ull> mod;
  const int n;

public:
  RollingHash(const vector<ull> &mod, const ull &base)
      : mod(mod), base(base), n((int)mod.size()) {}
  bool contain(const string &s, const string &t) { // sのsubstringにtが存在するか
    return contain(s, t, 0, s.size());
  }
  bool contain(const string &s, const string &t, int l,
               int r) { // sの[l,r)にsubstringにtが存在するか
    int sl = (int)s.size(), tl = (int)t.size();
    chmin(r, sl);
    chmax(l, 0);
    int ran = r - l;
    if (ran < tl)
      return false;
    vector<ull> sh(n, 0), th(n, 0), p(n, 1);
    bool flag = true;
    for (int i = 0; i < n; ++i) {
      for (int j = l; j < l + tl; ++j) {
        sh[i] = sh[i] * base + s[j];
        if (sh[i] > mod[i])
          sh[i] %= mod[i];
        th[i] = th[i] * base + t[j - l];
        if (th[i] > mod[i])
          th[i] %= mod[i];
        p[i] *= base;
        if (p[i] > mod[i])
          p[i] %= mod[i];
      }
    }
    for (int i = 0; i < n; ++i) {
      if (th[i] != sh[i])
        flag = false;
    }
    if (flag) {
      return true;
    }
    for (int j = l + tl; j < r; ++j) {
      flag = true;
      for (int i = 0; i < n; ++i) {
        sh[i] = sh[i] * base + s[j];
        if (sh[i] < p[i] * s[j - tl]) {
          sh[i] += mod[i] * s[j - tl];
        }
        sh[i] -= p[i] * s[j - tl];
        if (sh[i] > mod[i])
          sh[i] %= mod[i];
      }
      for (int i = 0; i < n; ++i) {
        if (th[i] != sh[i])
          flag = false;
      }
      if (flag) {
        return true;
      }
    }
    return false;
  }
  vector<int> find(const string &s, const string &t) {
    return find(s, t, 0, s.size());
  }
  vector<int> find(const string &s, const string &t, int l,
                   int r) { // sのsubstringがtである先頭のindexを返す
    int sl = (int)s.size(), tl = (int)t.size();
    vector<int> res;
    int ran = r - l;
    if (ran < tl)
      return res;
    vector<ull> sh(n, 0), th(n, 0), p(n, 1);
    bool flag = true;
    for (int i = 0; i < n; ++i) {
      for (int j = l; j < l + tl; ++j) {
        sh[i] = sh[i] * base + s[j];
        if (sh[i] > mod[i])
          sh[i] %= mod[i];
        th[i] = th[i] * base + t[j - l];
        if (th[i] > mod[i])
          th[i] %= mod[i];
        p[i] *= base;
        if (p[i] > mod[i])
          p[i] %= mod[i];
      }
    }
    for (int i = 0; i < n; ++i)
      if (th[i] != sh[i])
        flag = false;
    if (flag)
      res.push_back(0);
    for (int j = l + tl; j < r; ++j) {
      flag = true;
      for (int i = 0; i < n; ++i) {
        sh[i] = sh[i] * base + s[j];
        if (sh[i] < p[i] * s[j - tl]) {
          sh[i] += mod[i] * s[j - tl];
        }
        sh[i] -= p[i] * s[j - tl];
        if (sh[i] > mod[i])
          sh[i] %= mod[i];
      }
      for (int i = 0; i < n; ++i)
        if (th[i] != sh[i])
          flag = false;
      if (flag)
        res.push_back(j - tl + 1);
    }
    return res;
  }
};

int main() {
  IOS;
  int n;
  string s;
  cin >> n >> s;
  const vector<ull> mod = {1000000033, 1000000087};
  random_device rnd;
  mt19937 mt(rnd());
  const ull base = mt() + 1e5;
  using RH = RollingHash;
  RH r(mod, base);
  int lb = -1, ub = n + 1;
  while (ub - lb > 1) {
    int mid = (ub + lb) / 2;
    bool flag = false;
    REP(i, n - mid) {
      string tmp;
      FOR(j, i, i + mid) { tmp += s[j]; }
      if (r.contain(s, tmp, i + mid, n)) {
        flag = true;
        break;
      }
    }
    if (flag) {
      lb = mid;
    } else {
      ub = mid;
    }
  }
  put(lb);
  return 0;
}

Fixed submission:
#include <bits/stdc++.h>
using namespace std;
#define Rep(i, n) for (int i = 0; i < (int)(n); i++)
#define For(i, n1, n2) for (int i = (int)(n1); i < (int)(n2); i++)
#define REP(i, n) for (ll i = 0; i < (ll)(n); i++)
#define RREP(i, n) for (ll i = ((ll)(n)-1); i >= 0; i--)
#define FOR(i, n1, n2) for (ll i = (ll)(n1); i < (ll)(n2); i++)
#define RFOR(i, n1, n2) for (ll i = ((ll)(n1)-1); i >= (ll)(n2); i--)
#define all(a) (a).begin(), (a).end()
#define SORT(a) sort((a).begin(), (a).end())
#define oorret 0
#define oor(x)                                                                 \
  [&]() {                                                                      \
    try {                                                                      \
      x;                                                                       \
    } catch (const out_of_range &oor) {                                        \
      return oorret;                                                           \
    }                                                                          \
    return x;                                                                  \
  }()
#define IOS cin.tie(0), ios::sync_with_stdio(false)
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> P;
template <typename T1, typename T2> inline bool chmin(T1 &a, T2 b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
template <typename T1, typename T2> inline bool chmax(T1 &a, T2 b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class Type> struct is_vector : std::false_type {};
template <class ValueType, class Alloc>
struct is_vector<std::vector<ValueType, Alloc>> : std::true_type {};
template <typename T>
inline ostream &operator<<(ostream &out, const vector<T> &v) {
  if (v.empty())
    return out;
  constexpr bool is_vector_v = is_vector<T>::value;
  if (is_vector_v)
    for (auto itr = v.begin(); itr != v.end();)
      out << (*itr), out << ((++itr != v.end()) ? "\n" : "");
  else
    for (auto itr = v.begin(); itr != v.end();)
      out << (*itr), out << ((++itr != v.end()) ? " " : "");
  return out;
}
inline void put() {}
template <class T> inline void put(const T &first) {
  std::cout << first << "\n";
}
template <class T, class... N>
inline void put(const T &first, const N &...rest) {
  std::cout << first << " ";
  put(rest...);
}
inline void putn() {}
template <class T, class... N>
inline void putn(const T &first, const N &...rest) {
  std::cout << first << "\n";
  putn(rest...);
}

class RollingHash {
private:
  const ull base;
  const vector<ull> mod;
  const int n;

public:
  RollingHash(const vector<ull> &mod, const ull &base)
      : mod(mod), base(base), n((int)mod.size()) {}
  bool contain(const string &s, const string &t) { // sのsubstringにtが存在するか
    return contain(s, t, 0, s.size());
  }
  bool contain(const string &s, const string &t, int l,
               int r) { // sの[l,r)にsubstringにtが存在するか
    int sl = (int)s.size(), tl = (int)t.size();
    chmin(r, sl);
    chmax(l, 0);
    int ran = r - l;
    if (ran < tl)
      return false;
    vector<ull> sh(n, 0), th(n, 0), p(n, 1);
    bool flag = true;
    for (int i = 0; i < n; ++i) {
      for (int j = l; j < l + tl; ++j) {
        sh[i] = sh[i] * base + s[j];
        if (sh[i] > mod[i])
          sh[i] %= mod[i];
        th[i] = th[i] * base + t[j - l];
        if (th[i] > mod[i])
          th[i] %= mod[i];
        p[i] *= base;
        if (p[i] > mod[i])
          p[i] %= mod[i];
      }
    }
    for (int i = 0; i < n; ++i) {
      if (th[i] != sh[i])
        flag = false;
    }
    if (flag) {
      return true;
    }
    for (int j = l + tl; j < r; ++j) {
      flag = true;
      for (int i = 0; i < n; ++i) {
        sh[i] = sh[i] * base + s[j];
        if (sh[i] < p[i] * s[j - tl]) {
          sh[i] += mod[i] * s[j - tl];
        }
        sh[i] -= p[i] * s[j - tl];
        if (sh[i] > mod[i])
          sh[i] %= mod[i];
      }
      for (int i = 0; i < n; ++i) {
        if (th[i] != sh[i])
          flag = false;
      }
      if (flag) {
        return true;
      }
    }
    return false;
  }
  vector<int> find(const string &s, const string &t) {
    return find(s, t, 0, s.size());
  }
  vector<int> find(const string &s, const string &t, int l,
                   int r) { // sのsubstringがtである先頭のindexを返す
    int sl = (int)s.size(), tl = (int)t.size();
    vector<int> res;
    int ran = r - l;
    if (ran < tl)
      return res;
    vector<ull> sh(n, 0), th(n, 0), p(n, 1);
    bool flag = true;
    for (int i = 0; i < n; ++i) {
      for (int j = l; j < l + tl; ++j) {
        sh[i] = sh[i] * base + s[j];
        if (sh[i] > mod[i])
          sh[i] %= mod[i];
        th[i] = th[i] * base + t[j - l];
        if (th[i] > mod[i])
          th[i] %= mod[i];
        p[i] *= base;
        if (p[i] > mod[i])
          p[i] %= mod[i];
      }
    }
    for (int i = 0; i < n; ++i)
      if (th[i] != sh[i])
        flag = false;
    if (flag)
      res.push_back(0);
    for (int j = l + tl; j < r; ++j) {
      flag = true;
      for (int i = 0; i < n; ++i) {
        sh[i] = sh[i] * base + s[j];
        if (sh[i] < p[i] * s[j - tl]) {
          sh[i] += mod[i] * s[j - tl];
        }
        sh[i] -= p[i] * s[j - tl];
        if (sh[i] > mod[i])
          sh[i] %= mod[i];
      }
      for (int i = 0; i < n; ++i)
        if (th[i] != sh[i])
          flag = false;
      if (flag)
        res.push_back(j - tl + 1);
    }
    return res;
  }
};

int main() {
  IOS;
  int n;
  string s;
  cin >> n >> s;
  const vector<ull> mod = {2000000011};
  random_device rnd;
  mt19937 mt(rnd());
  const ull base = mt() + 1e5;
  using RH = RollingHash;
  RH r(mod, base);
  int lb = -1, ub = n + 1;
  while (ub - lb > 1) {
    int mid = (ub + lb) / 2;
    bool flag = false;
    REP(i, n - mid) {
      string tmp;
      FOR(j, i, i + mid) { tmp += s[j]; }
      if (r.contain(s, tmp, i + mid, n)) {
        flag = true;
        break;
      }
    }
    if (flag) {
      lb = mid;
    } else {
      ub = mid;
    }
  }
  put(lb);
  return 0;
}