Problem p02962 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <cstdint>
#include <cstdlib>
#include <iostream>
#include <map>
#include <string>
#include <vector>
template <typename T> void fin(T const &t) {
  std::cout << t << std::endl;
  exit(0);
}

template <int MAXV> struct scc {
  std::vector<int> G[MAXV], rG[MAXV], vs;
  bool used[MAXV];
  // int cmp[MAXV];
  scc() {}
  void dfs(int v) {
    used[v] = true;
    for (auto c : G[v])
      if (!used[c])
        dfs(c);
    vs.push_back(v);
  }
  void rdfs(int v, int k) {
    used[v] = true;
    // cmp[v] = k;
    for (auto c : rG[v])
      if (!used[c])
        rdfs(c, k);
  }
  int build(int V) {
    std::fill_n(used, V, false);
    vs.clear();
    for (int v = 0; v < V; ++v)
      if (!used[v])
        dfs(v);
    std::fill_n(used, V, false);
    int k = 0;
    for (int i = vs.size() - 1; i >= 0; --i) {
      if (!used[vs[i]])
        rdfs(vs[i], k++);
    }
    return k;
  }
  void add_edge(int fr, int to) {
    G[fr].push_back(to);
    rG[to].push_back(fr);
  }
};

int const MAXN = 5e5;

scc<MAXN> sc;
int depth[MAXN];
int calc_depth(int v) {
  if (depth[v] >= 0)
    return depth[v];
  int res = -1;
  for (auto c : sc.G[v])
    res = std::max(res, calc_depth(c));
  ++res;
  return depth[v] = res;
}

struct rolling_hash {
  __uint128_t m_, b_, bl_;
  int l_;
  rolling_hash(int64_t mod, int64_t base, int length)
      : m_(mod), b_(base), l_(length) {
    bl_ = 1;
    __uint128_t v = b_;
    while (length > 0) {
      if (length & 1)
        (bl_ *= v) %= m_;
      length /= 2;
      (v *= v) %= m_;
    }
  }
  int64_t hash(char const *s) {
    __uint128_t res = 0;
    for (int i = 0; i < l_; ++i)
      (res = res * b_ % m_ + s[i]) %= m_;
    return res;
  }
  int64_t next(int64_t hash, char in_c, char out_c) {
    __uint128_t h = hash;
    (h = h * b_ % m_ + in_c + (m_ - out_c) * bl_ % m_) %= m_;
    return h;
  }
};

int main() {
  std::string S, T;
  std::cin >> S >> T;
  int N = S.size(), M = T.size(), K = N + M - 1;
  std::string U = S + S.substr(0, M - 1);
  // rolling_hash rh1((int64_t)1e18+3, (int64_t)1e9+7, M);
  rolling_hash rh1((int64_t)999999937, (int64_t)17, M);
  int64_t t1 = rh1.hash(T.c_str());
  int64_t u1 = rh1.hash(U.c_str());
  std::vector<int> v;
  for (int i = 0; i < N; ++i) {
    if (t1 == u1)
      v.push_back(i);
    if (M + i >= K)
      break;
    u1 = rh1.next(u1, U[M + i], U[i]);
  }

  if (v.size() < 1)
    fin(0);
  for (int fr : v) {
    int to = (fr + M) % N;
    if (fr == to)
      fin(-1);
    sc.add_edge(fr, to);
  }
  if (sc.build(N) < N)
    fin(-1);
  std::fill_n(depth, N, -1);
  int ans = 0;
  for (int i = 0; i < N; ++i) {
    ans = std::max(ans, calc_depth(i));
  }
  fin(ans);

  return 0;
}


Fixed submission:
#include <algorithm>
#include <cstdint>
#include <cstdlib>
#include <iostream>
#include <map>
#include <string>
#include <vector>
template <typename T> void fin(T const &t) {
  std::cout << t << std::endl;
  exit(0);
}

template <int MAXV> struct scc {
  std::vector<int> G[MAXV], rG[MAXV], vs;
  bool used[MAXV];
  // int cmp[MAXV];
  scc() {}
  void dfs(int v) {
    used[v] = true;
    for (auto c : G[v])
      if (!used[c])
        dfs(c);
    vs.push_back(v);
  }
  void rdfs(int v, int k) {
    used[v] = true;
    // cmp[v] = k;
    for (auto c : rG[v])
      if (!used[c])
        rdfs(c, k);
  }
  int build(int V) {
    std::fill_n(used, V, false);
    vs.clear();
    for (int v = 0; v < V; ++v)
      if (!used[v])
        dfs(v);
    std::fill_n(used, V, false);
    int k = 0;
    for (int i = vs.size() - 1; i >= 0; --i) {
      if (!used[vs[i]])
        rdfs(vs[i], k++);
    }
    return k;
  }
  void add_edge(int fr, int to) {
    G[fr].push_back(to);
    rG[to].push_back(fr);
  }
};

int const MAXN = 5e5;

scc<MAXN> sc;
int depth[MAXN];
int calc_depth(int v) {
  if (depth[v] >= 0)
    return depth[v];
  int res = -1;
  for (auto c : sc.G[v])
    res = std::max(res, calc_depth(c));
  ++res;
  return depth[v] = res;
}

struct rolling_hash {
  __uint128_t m_, b_, bl_;
  int l_;
  rolling_hash(int64_t mod, int64_t base, int length)
      : m_(mod), b_(base), l_(length) {
    bl_ = 1;
    __uint128_t v = b_;
    while (length > 0) {
      if (length & 1)
        (bl_ *= v) %= m_;
      length /= 2;
      (v *= v) %= m_;
    }
  }
  int64_t hash(char const *s) {
    __uint128_t res = 0;
    for (int i = 0; i < l_; ++i)
      (res = res * b_ % m_ + s[i]) %= m_;
    return res;
  }
  int64_t next(int64_t hash, char in_c, char out_c) {
    __uint128_t h = hash;
    (h = h * b_ % m_ + in_c + (m_ - out_c) * bl_ % m_) %= m_;
    return h;
  }
};

int main() {
  std::string S, T;
  std::cin >> S >> T;
  int N = S.size(), M = T.size(), K = N + M - 1;
  std::string U = S;
  for (int i = 0; i < (M - 1) / N; ++i)
    U += S;
  U += S.substr(0, K - U.size());
  // rolling_hash rh1((int64_t)1e18+3, (int64_t)1e9+7, M);
  rolling_hash rh1((int64_t)999999937, (int64_t)17, M);
  int64_t t1 = rh1.hash(T.c_str());
  int64_t u1 = rh1.hash(U.c_str());
  std::vector<int> v;
  for (int i = 0; i < N; ++i) {
    if (t1 == u1)
      v.push_back(i);
    if (M + i >= K)
      break;
    u1 = rh1.next(u1, U[M + i], U[i]);
  }

  if (v.size() < 1)
    fin(0);
  for (int fr : v) {
    int to = (fr + M) % N;
    if (fr == to)
      fin(-1);
    sc.add_edge(fr, to);
  }
  if (sc.build(N) < N)
    fin(-1);
  std::fill_n(depth, N, -1);
  int ans = 0;
  for (int i = 0; i < N; ++i) {
    ans = std::max(ans, calc_depth(i));
  }
  fin(ans);

  return 0;
}