Problem p02962 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

struct RollingHash {
  vector<long long> hash, power;
  const int seed = 10007, mod = 1e9 + 7;

  RollingHash(const string &s) {
    int n = (int)s.size();
    hash.assign(n + 1, 0);
    power.assign(n + 1, 1);
    for (int i = 0; i < n; ++i)
      power[i + 1] = power[i] * seed % mod;

    for (int i = 0; i < n; ++i) {
      hash[i + 1] = (hash[i] * seed + s[i]) % mod;
      power[i + 1] = power[i] * seed % mod;
    }
  }

  // [l, r)
  long long get_hash(int l, int r) {
    long long ret = (hash[r] - hash[l] * power[r - l] % mod + mod) % mod;
    return ret;
  }
};

struct UnionFind {
  vector<int> par, weight;
  UnionFind(int n) : par(n, -1), weight(n) {}
  bool unite(int x, int y, int w = 0) {
    x = root(x);
    y = root(y);
    if (x == y)
      return false;
    if (par[x] > par[y])
      swap(x, y), w = -w;
    par[x] += par[y];
    par[y] = x;
    return true;
  }
  bool same(int x, int y) { return root(x) == root(y); }
  int root(int x) {
    if (par[x] < 0)
      return x;
    int r = root(par[x]);
    return par[x] = r;
  }
  int sizeOf(int x) { return -par[root(x)]; }
};

int main() {
  string s, t;
  cin >> s >> t;
  int n = s.size();
  s = s + s + s;
  while (t.size() * 2 > s.size())
    s += s;

  int N = s.size();
  int m = t.size();
  vector<bool> match(N);

  RollingHash rh1(s), rh2(t);
  unsigned long long thash = rh2.get_hash(0, m);

  for (int i = 0; i < N - m; ++i) {
    if (rh1.get_hash(i, i + m) == thash)
      match[i] = true;
  }

  // loop check & count
  UnionFind uf(n);
  for (int i = 0; i < n; ++i) {
    if (match[i] && match[(i + m) % n]) {
      if (!uf.unite(i, (i + m) % n)) {
        cout << -1 << endl;
        return 0;
      }
    }
  }

  int ans = 0;
  for (int i = 0; i < N; ++i)
    if (match[i])
      ans = max(ans, uf.sizeOf(i));
  cout << ans << endl;
  return 0;
}


Fixed submission:
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

struct RollingHash {
  vector<long long> hash, power;
  const int seed = 10007, mod = 1e9 + 7;

  RollingHash(const string &s) {
    int n = (int)s.size();
    hash.assign(n + 1, 0);
    power.assign(n + 1, 1);
    for (int i = 0; i < n; ++i)
      power[i + 1] = power[i] * seed % mod;

    for (int i = 0; i < n; ++i) {
      hash[i + 1] = (hash[i] * seed + s[i]) % mod;
      power[i + 1] = power[i] * seed % mod;
    }
  }

  // [l, r)
  long long get_hash(int l, int r) {
    long long ret = (hash[r] - hash[l] * power[r - l] % mod + mod) % mod;
    return ret;
  }
};

struct UnionFind {
  vector<int> par, weight;
  UnionFind(int n) : par(n, -1), weight(n) {}
  bool unite(int x, int y, int w = 0) {
    x = root(x);
    y = root(y);
    if (x == y)
      return false;
    if (par[x] > par[y])
      swap(x, y), w = -w;
    par[x] += par[y];
    par[y] = x;
    return true;
  }
  bool same(int x, int y) { return root(x) == root(y); }
  int root(int x) {
    if (par[x] < 0)
      return x;
    int r = root(par[x]);
    return par[x] = r;
  }
  int sizeOf(int x) { return -par[root(x)]; }
};

int main() {
  string s, t;
  cin >> s >> t;
  int n = s.size();
  s = s + s + s;
  while (t.size() * 2 > s.size())
    s += s;

  int N = s.size();
  int m = t.size();
  vector<bool> match(N);

  RollingHash rh1(s), rh2(t);
  unsigned long long thash = rh2.get_hash(0, m);

  for (int i = 0; i < N - m; ++i) {
    if (rh1.get_hash(i, i + m) == thash)
      match[i] = true;
  }

  // loop check & count
  UnionFind uf(N);
  for (int i = 0; i < n; ++i) {
    if (match[i] && match[(i + m) % n]) {
      if (!uf.unite(i, (i + m) % n)) {
        cout << -1 << endl;
        return 0;
      }
    }
  }

  int ans = 0;
  for (int i = 0; i < N; ++i)
    if (match[i])
      ans = max(ans, uf.sizeOf(i));
  cout << ans << endl;
  return 0;
}