Problem p04018 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <bits/stdc++.h>

#if MYDEBUG
#include "lib/cp_debug.hpp"
#else
#define DBG(...) ;
#endif
#if __cplusplus <= 201402L
template <typename T> T gcd(T a, T b) {
  return ((a % b == 0) ? b : gcd(b, a % b));
}
template <typename T> T lcm(T a, T b) { return a / gcd(a, b) * b; }
#endif
using LL = long long;
constexpr LL LINF = 334ll << 53;
constexpr int INF = 15 << 26;
constexpr LL MOD = 1E9 + 7;

namespace Problem {
using namespace std;
// newest
template <long long Mod = MOD> class Modint {
public:
  long long v;

  Modint(const Modint &x) { v = x.v; }
  explicit Modint(int x) {
    if (x < 0 or Mod <= x)
      x %= Mod;
    if (x < 0)
      x += Mod;
    v = x;
  }
  explicit Modint(long long x) {
    if (x < 0 or Mod <= x)
      x %= Mod;
    if (x < 0)
      x += Mod;
    v = x;
  }
  explicit Modint(unsigned x) {
    if (Mod <= x)
      x %= Mod;
    v = x;
  }
  explicit Modint(unsigned long long x) {
    if (Mod <= x)
      x %= Mod;
    v = x;
  }
  template <typename T> explicit Modint(T x) {
    if (x < 0 or Mod <= x)
      x %= Mod;
    v = x;
  }
  Modint() : v(0) {}
  long long get() const { return v; }
  Modint mpow(Modint &n) const { return mpow(n.v); }
  Modint mpow(long long n) const {
    long long i = 1, p = v;
    Modint ret(1);
    while (i <= n) {
      if (i & n)
        ret *= p;
      i = (i << 1);
      p = (p * p) % Mod;
    }
    return ret;
  }
  Modint operator-() const { return (v ? Modint(Mod - v) : Modint(0)); }
  explicit operator int() const { return v; }
  explicit operator long long() const { return v; }
  Modint &operator+=(const Modint &a) {
    v = (v + a.v);
    if (v >= Mod)
      v -= Mod;
    return *this;
  }
  Modint &operator-=(const Modint &a) {
    v = (v - a.v);
    if (v < 0)
      v += Mod;
    return *this;
  }
  Modint &operator*=(const Modint &a) {
    v = (v * a.v) % Mod;
    return *this;
  }
  Modint &operator/=(const Modint &a) {
    v = (v * a.mpow(Mod - 2).v) % Mod;
    return *this;
  }
  template <class T> Modint &operator+=(const T &a) {
    v = (v + Modint(a).v);
    if (v >= Mod)
      v -= Mod;
    return *this;
  }
  template <class T> Modint &operator-=(const T &a) {
    v = (v - Modint(a).v);
    if (v < 0)
      v += Mod;
    return *this;
  }
  template <class T> Modint &operator*=(const T &a) {
    v = (v * Modint(a).v) % Mod;
    return *this;
  }
  template <class T> Modint &operator/=(const T &a) {
    v = (v * Modint(a).mpow(Mod - 2).v) % Mod;
    return *this;
  }
  friend Modint operator+(const Modint &a, const Modint &b) {
    return Modint(a) += b;
  }
  friend Modint operator-(const Modint &a, const Modint &b) {
    return Modint(a) -= b;
  }
  friend Modint operator*(const Modint &a, const Modint &b) {
    return Modint(a) *= b;
  }
  friend Modint operator/(const Modint &a, const Modint &b) {
    return Modint(a) /= b;
  }
  template <class T, class U> friend Modint operator+(const T &a, const U &b) {
    return Modint(a) += Modint(b);
  }
  template <class T, class U> friend Modint operator-(const T &a, const U &b) {
    return Modint(a) -= Modint(b);
  }
  template <class T, class U> friend Modint operator*(const T &a, const U &b) {
    return Modint(a) *= Modint(b);
  }
  template <class T, class U> friend Modint operator/(const T &a, const U &b) {
    return Modint(a) /= Modint(b);
  }
};

template <long long M> ostream &operator<<(ostream &os, const Modint<M> m) {
  return os << m.v;
}

struct Hash {
  random_device rnd;
  mt19937 mt;
  uniform_int_distribution<LL> dist;
  vector<long long> prime, base;
  vector<vector<long long>> value, memo;
  int n;
  Hash(const vector<long long> &primes)
      : mt(rnd()), dist(1000, 1e7), prime(primes), n(primes.size()) {
    for (int i = 0; i < n; ++i)
      base.push_back(dist(mt));
    value.push_back({0LL, 0LL, 0LL});
    memo.push_back({1LL, 1LL, 1LL});
  };
  Hash() : Hash({999999937LL, 1000000007LL}){};
  void push_back(long long x) {
    int l = value.size();
    value.push_back(vector<long long>(n));
    memo.push_back(vector<long long>(n));
    for (int i = 0; i < n; ++i) {
      value[l][i] = (value[l - 1][i] * base[i] + x) % prime[i];
      memo[l][i] = memo[l - 1][i] * base[i] % prime[i];
    }
  }
  vector<long long> get(int l, int r) {
    // get the hash of inteval [l,r)
    auto R = value[r];
    auto L = value[l];
    for (int i = 0; i < n; ++i) {
      L[i] = L[i] * memo[r - l][i] % prime[i];
      R[i] = ((R[i] - L[i]) % prime[i] + prime[i]) % prime[i];
      // R[i] *= modpow(base[i], (r - l) * (prime[i] - 2) % (prime[i] - 1),
      // prime[i]);
    }
    return R;
  }
  bool equals(int l, int r, int l2, int r2) { return get(l, r) == get(l2, r2); }
};
class Solver {
public:
  string s;
  int n;
  Solver(string s) : s(s), n(s.length()){};
  int minPeriod(string str) {
    int l = str.length();
    for (int i = 1; i < l; ++i) {
      if (l % i == 0) {
        string tmp = str;
        rotate(tmp.begin(), tmp.begin() + i, tmp.end());
        if (tmp == str)
          return i;
      }
    }
    return n;
  }
  void solve() {
    int p = minPeriod(s);
    if (p == n) {
      cout << 1 << endl;
      cout << 1 << endl;
    } else if (p == 1) {
      cout << n << endl;
      cout << 1 << endl;
    } else {
      cout << 2 << endl;
      string rev = s;
      reverse(rev.begin(), rev.end());
      Hash hs({999999937LL, 1000000007LL, 1000000009LL}),
          rhs({999999937LL, 1000000007LL, 1000000009LL});
      vector<int> isGood(n, 1);
      for (int i = 0; i < n; ++i) {
        hs.push_back(s[i] - 'a');
        rhs.push_back(rev[i] - 'a');
      }
      for (int i = 1; i < n; ++i) {
        auto hash0i = hs.get(0, i);
        for (int j = i * 2; j < n; j += i) {
          if (hs.get(j - i, j) != hash0i)
            break;
          isGood[j] = 0;
        }
      }
      for (int i = 1; i < n; ++i) {
        auto hash0i = rhs.get(0, i);
        for (int j = i * 2; j < n; j += i) {
          if (rhs.get(j - i, j) != hash0i)
            break;
          isGood[n - j] = 0;
        }
      }
      cout << accumulate(isGood.begin() + 1, isGood.end(), 0) << endl;
    }
  }
};
} // namespace Problem

int main() {
  std::cin.tie(0);
  std::ios_base::sync_with_stdio(false);
  // std::cout << std::fixed << std::setprecision(12);
  std::string s;
  std::cin >> s;

  Problem::Solver sol(s);
  sol.solve();
  return 0;
}


Fixed submission:
#include <bits/stdc++.h>

#if MYDEBUG
#include "lib/cp_debug.hpp"
#else
#define DBG(...) ;
#endif
#if __cplusplus <= 201402L
template <typename T> T gcd(T a, T b) {
  return ((a % b == 0) ? b : gcd(b, a % b));
}
template <typename T> T lcm(T a, T b) { return a / gcd(a, b) * b; }
#endif
using LL = long long;
constexpr LL LINF = 334ll << 53;
constexpr int INF = 15 << 26;
constexpr LL MOD = 1E9 + 7;

namespace Problem {
using namespace std;
// newest
template <long long Mod = MOD> class Modint {
public:
  long long v;

  Modint(const Modint &x) { v = x.v; }
  explicit Modint(int x) {
    if (x < 0 or Mod <= x)
      x %= Mod;
    if (x < 0)
      x += Mod;
    v = x;
  }
  explicit Modint(long long x) {
    if (x < 0 or Mod <= x)
      x %= Mod;
    if (x < 0)
      x += Mod;
    v = x;
  }
  explicit Modint(unsigned x) {
    if (Mod <= x)
      x %= Mod;
    v = x;
  }
  explicit Modint(unsigned long long x) {
    if (Mod <= x)
      x %= Mod;
    v = x;
  }
  template <typename T> explicit Modint(T x) {
    if (x < 0 or Mod <= x)
      x %= Mod;
    v = x;
  }
  Modint() : v(0) {}
  long long get() const { return v; }
  Modint mpow(Modint &n) const { return mpow(n.v); }
  Modint mpow(long long n) const {
    long long i = 1, p = v;
    Modint ret(1);
    while (i <= n) {
      if (i & n)
        ret *= p;
      i = (i << 1);
      p = (p * p) % Mod;
    }
    return ret;
  }
  Modint operator-() const { return (v ? Modint(Mod - v) : Modint(0)); }
  explicit operator int() const { return v; }
  explicit operator long long() const { return v; }
  Modint &operator+=(const Modint &a) {
    v = (v + a.v);
    if (v >= Mod)
      v -= Mod;
    return *this;
  }
  Modint &operator-=(const Modint &a) {
    v = (v - a.v);
    if (v < 0)
      v += Mod;
    return *this;
  }
  Modint &operator*=(const Modint &a) {
    v = (v * a.v) % Mod;
    return *this;
  }
  Modint &operator/=(const Modint &a) {
    v = (v * a.mpow(Mod - 2).v) % Mod;
    return *this;
  }
  template <class T> Modint &operator+=(const T &a) {
    v = (v + Modint(a).v);
    if (v >= Mod)
      v -= Mod;
    return *this;
  }
  template <class T> Modint &operator-=(const T &a) {
    v = (v - Modint(a).v);
    if (v < 0)
      v += Mod;
    return *this;
  }
  template <class T> Modint &operator*=(const T &a) {
    v = (v * Modint(a).v) % Mod;
    return *this;
  }
  template <class T> Modint &operator/=(const T &a) {
    v = (v * Modint(a).mpow(Mod - 2).v) % Mod;
    return *this;
  }
  friend Modint operator+(const Modint &a, const Modint &b) {
    return Modint(a) += b;
  }
  friend Modint operator-(const Modint &a, const Modint &b) {
    return Modint(a) -= b;
  }
  friend Modint operator*(const Modint &a, const Modint &b) {
    return Modint(a) *= b;
  }
  friend Modint operator/(const Modint &a, const Modint &b) {
    return Modint(a) /= b;
  }
  template <class T, class U> friend Modint operator+(const T &a, const U &b) {
    return Modint(a) += Modint(b);
  }
  template <class T, class U> friend Modint operator-(const T &a, const U &b) {
    return Modint(a) -= Modint(b);
  }
  template <class T, class U> friend Modint operator*(const T &a, const U &b) {
    return Modint(a) *= Modint(b);
  }
  template <class T, class U> friend Modint operator/(const T &a, const U &b) {
    return Modint(a) /= Modint(b);
  }
};

template <long long M> ostream &operator<<(ostream &os, const Modint<M> m) {
  return os << m.v;
}

struct Hash {
  random_device rnd;
  mt19937 mt;
  uniform_int_distribution<LL> dist;
  vector<long long> prime, base;
  vector<vector<long long>> value, memo;
  int n;
  Hash(const vector<long long> &primes)
      : mt(rnd()), dist(1000, 1e7), prime(primes), n(primes.size()) {
    for (int i = 0; i < n; ++i)
      base.push_back(dist(mt));
    value.push_back({0LL, 0LL, 0LL});
    memo.push_back({1LL, 1LL, 1LL});
  };
  Hash() : Hash({999999937LL, 1000000007LL}){};
  void push_back(long long x) {
    int l = value.size();
    value.push_back(vector<long long>(n));
    memo.push_back(vector<long long>(n));
    for (int i = 0; i < n; ++i) {
      value[l][i] = (value[l - 1][i] * base[i] + x) % prime[i];
      memo[l][i] = memo[l - 1][i] * base[i] % prime[i];
    }
  }
  vector<long long> get(int l, int r) {
    // get the hash of inteval [l,r)
    auto R = value[r];
    auto L = value[l];
    for (int i = 0; i < n; ++i) {
      L[i] = L[i] * memo[r - l][i] % prime[i];
      R[i] = (R[i] - L[i]) % prime[i];
      if (R[i] < 0)
        R[i] += prime[i];
      // R[i] *= modpow(base[i], (r - l) * (prime[i] - 2) % (prime[i] - 1),
      // prime[i]);
    }
    return R;
  }
  bool equals(int l, int r, int l2, int r2) { return get(l, r) == get(l2, r2); }
};
class Solver {
public:
  string s;
  int n;
  Solver(string s) : s(s), n(s.length()){};
  int minPeriod(string str) {
    int l = str.length();
    for (int i = 1; i < l; ++i) {
      if (l % i == 0) {
        string tmp = str;
        rotate(tmp.begin(), tmp.begin() + i, tmp.end());
        if (tmp == str)
          return i;
      }
    }
    return n;
  }
  void solve() {
    int p = minPeriod(s);
    if (p == n) {
      cout << 1 << endl;
      cout << 1 << endl;
    } else if (p == 1) {
      cout << n << endl;
      cout << 1 << endl;
    } else {
      cout << 2 << endl;
      string rev = s;
      reverse(rev.begin(), rev.end());
      Hash hs({999999937LL, 1000000007LL, 1000000009LL}),
          rhs({999999937LL, 1000000007LL, 1000000009LL});
      vector<int> isGood(n, 1);
      for (int i = 0; i < n; ++i) {
        hs.push_back(s[i] - 'a');
        rhs.push_back(rev[i] - 'a');
      }
      for (int i = 1; i < n; ++i) {
        auto hash0i = hs.get(0, i);
        for (int j = i * 2; j < n; j += i) {
          if (hs.get(j - i, j) != hash0i)
            break;
          isGood[j] = 0;
        }
      }
      for (int i = 1; i < n; ++i) {
        auto hash0i = rhs.get(0, i);
        for (int j = i * 2; j < n; j += i) {
          if (rhs.get(j - i, j) != hash0i)
            break;
          isGood[n - j] = 0;
        }
      }
      cout << accumulate(isGood.begin() + 1, isGood.end(), 0) << endl;
    }
  }
};
} // namespace Problem

int main() {
  std::cin.tie(0);
  std::ios_base::sync_with_stdio(false);
  // std::cout << std::fixed << std::setprecision(12);
  std::string s;
  std::cin >> s;

  Problem::Solver sol(s);
  sol.solve();
  return 0;
}