Problem p02913 (C++)

Buggy submission (status: Time Limit Exceeded):
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("avx")
#include <bits/stdc++.h>
constexpr int INF = 2147483647;
constexpr long long int INF_LL = 9223372036854775807;
constexpr int MOD = 1000000007;
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;

// modint 2^61-1
class RHint {
private:
  const ull MASK30 = (1UL << 30) - 1;
  const ull MASK31 = (1UL << 31) - 1;
  const ull RMOD = (1UL << 61) - 1;
  inline ull Mul(ull a, ull b) {
    ull au = a >> 31;
    ull ad = a & MASK31;
    ull bu = b >> 31;
    ull bd = b & MASK31;
    ull mid = ad * bu + au * bd;
    ull midu = mid >> 30;
    ull midd = mid & MASK30;
    return (au * bu * 2 + midu + (midd << 31) + ad * bd);
  }
  // mod 2^61-1を計算する関数
  inline ull CalcMod(ull a) {
    a = (a & RMOD) + (a >> 61);
    if (a > RMOD)
      a -= RMOD;
    return a;
  }

public:
  ull val;

  RHint() { val = 0; };
  RHint(ull a) { val = CalcMod(a); }

  inline RHint operator+(const RHint &r) {
    return RHint(CalcMod(this->val + r.val));
  }
  inline RHint operator*(const RHint &r) {
    return RHint(Mul(this->val, r.val));
  }
  inline RHint &operator=(const RHint &r) {
    val = r.val;
    return *this;
  }
  inline RHint &operator+=(const RHint &r) {
    *this = *this + r;
    return *this;
  }
  inline RHint &operator*=(const RHint &r) {
    *this = *this * r;
    return *this;
  }
};
inline bool operator==(const RHint &l, const RHint &r) {
  return l.val == r.val;
}
inline bool operator!=(const RHint &l, const RHint &r) {
  return l.val != r.val;
}
class RollingHash {
private:
  const ull RMOD = (1UL << 61) - 1;
  const ull PV = RMOD * 3;
  RHint base;

public:
  vector<RHint> hash, pow;
  RollingHash(string s, ull b) {
    int l = s.size();
    base = RHint(b);
    hash = vector<RHint>(l + 1, 0);
    pow = vector<RHint>(l + 1, 1);
    for (int i = 0; i < l; i++) {
      hash[i + 1] = (hash[i] + RHint(s[i])) * base;
      pow[i + 1] = pow[i] * base;
    }
  }
  RHint get(int l, int r) {
    return RHint(hash[r].val + PV - (hash[l] * pow[r - l]).val);
  }
  RHint connect(RHint h1, RHint h2, int h2l) { return (h1 * pow[h2l] + h2); }
  int lcp(RollingHash &b, int l1, int r1, int l2, int r2) {
    int len = min(r1 - l1, r2 - l2);
    int low = -1, high = len + 1;
    while (high - low > 1) {
      int mid = (low + high) / 2;
      if (get(l1, l1 + mid) == b.get(l2, l2 + mid))
        low = mid;
      else
        high = mid;
    }
    return low;
  }
};

int main() {
  cin.tie(0);
  ios::sync_with_stdio(0);

  int N;
  cin >> N;
  string s;
  cin >> s;
  RollingHash S(s, 10007);
  int ans = 0;
  for (int i = 0; i < N; i++) {
    for (int j = i; j < N; j++) {
      ans = max(ans, S.lcp(S, i, j, j, N));
      // cout << S.lcp(S, i, j, j, N) << endl;
    }
  }
  cout << ans << endl;
}

Fixed submission:
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("avx")
#include <bits/stdc++.h>
constexpr int INF = 2147483647;
constexpr long long int INF_LL = 9223372036854775807;
constexpr int MOD = 1000000007;
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;

// modint 2^61-1
class RHint {
private:
  const ull MASK30 = (1UL << 30) - 1;
  const ull MASK31 = (1UL << 31) - 1;
  const ull RMOD = (1UL << 61) - 1;
  inline ull Mul(ull a, ull b) {
    ull au = a >> 31;
    ull ad = a & MASK31;
    ull bu = b >> 31;
    ull bd = b & MASK31;
    ull mid = ad * bu + au * bd;
    ull midu = mid >> 30;
    ull midd = mid & MASK30;
    return (au * bu * 2 + midu + (midd << 31) + ad * bd);
  }
  // mod 2^61-1を計算する関数
  inline ull CalcMod(ull a) {
    a = (a & RMOD) + (a >> 61);
    if (a > RMOD)
      a -= RMOD;
    return a;
  }

public:
  ull val;

  RHint() { val = 0; };
  RHint(ull a) { val = CalcMod(a); }

  inline RHint operator+(const RHint &r) {
    return RHint(CalcMod(this->val + r.val));
  }
  inline RHint operator*(const RHint &r) {
    return RHint(Mul(this->val, r.val));
  }
  inline RHint &operator=(const RHint &r) {
    val = r.val;
    return *this;
  }
  inline RHint &operator+=(const RHint &r) {
    *this = *this + r;
    return *this;
  }
  inline RHint &operator*=(const RHint &r) {
    *this = *this * r;
    return *this;
  }
};
inline bool operator==(const RHint &l, const RHint &r) {
  return l.val == r.val;
}
inline bool operator!=(const RHint &l, const RHint &r) {
  return l.val != r.val;
}
class RollingHash {
private:
  const ull RMOD = (1UL << 61) - 1;
  const ull PV = RMOD * 3;
  RHint base;

public:
  vector<RHint> hash, pow;
  RollingHash(string s, ull b) {
    int l = s.size();
    base = RHint(b);
    hash = vector<RHint>(l + 1, 0);
    pow = vector<RHint>(l + 1, 1);
    for (int i = 0; i < l; i++) {
      hash[i + 1] = (hash[i] + RHint(s[i])) * base;
      pow[i + 1] = pow[i] * base;
    }
  }
  RHint get(int l, int r) {
    return RHint(hash[r].val + PV - (hash[l] * pow[r - l]).val);
  }
  RHint connect(RHint h1, RHint h2, int h2l) { return (h1 * pow[h2l] + h2); }
  int lcp(RollingHash &b, int l1, int r1, int l2, int r2) {
    int len = min(r1 - l1, r2 - l2);
    int low = -1, high = len + 1;
    while (high - low > 1) {
      int mid = (low + high) / 2;
      if (get(l1, l1 + mid) == b.get(l2, l2 + mid))
        low = mid;
      else
        high = mid;
    }
    return low;
  }
};

int main() {
  cin.tie(0);
  ios::sync_with_stdio(0);

  int N;
  cin >> N;
  string s;
  cin >> s;
  RollingHash S(s, 10007);
  int ans = 0;
  for (int i = 0; i < N; i++) {
    for (int j = i; j < N; j++) {
      while (ans < j - i && j + ans < N &&
             S.get(i, i + ans + 1) == S.get(j, j + ans + 1))
        ans++;
    }
  }
  cout << ans << endl;
}