Problem p04018 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <vector>
using namespace std;

typedef pair<int, int> P;
#define rep(i, n) for (int i = 0; i < (n); i++)
#define all(c) (c).begin(), (c).end()
#define uniq(c) c.erase(unique(all(c)), (c).end())
#define index(xs, x) (int)(lower_bound(all(xs), x) - xs.begin())
#define _1 first
#define _2 second
#define pb push_back
#define INF 1145141919
#define MOD 1000000007

const int B = 321;
int N;
string S;
int dp[500001];
int num[500001];
int T[500001];
int pB[500001];
bool good_prefix[500000], good_suffix[500000];

inline int rhash(int l, int r) {
  return (1LL * ((T[r] + MOD - (l > 0 ? T[l - 1] : 0)) % MOD) * pB[N - l]) %
         MOD;
}

bool cycle(int l, int r, int d) {
  if (2 * d > r - l + 1)
    return false;
  // [l, r-d] = [l+d, r]
  return rhash(l, r - d) == rhash(l + d, r);
}

bool is_good(int l, int r) {
  int n = r - l + 1;
  for (int d = 1; d <= sqrt(n); d++) {
    if (n % d)
      continue;
    if (cycle(l, r, d))
      return false;
    if (cycle(l, r, n / d))
      return false;
  }
  return true;
}

signed main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cin >> S;
  N = S.length();
  pB[0] = 1;
  for (int i = 1; i <= 500000; i++)
    pB[i] = (1LL * pB[i - 1] * B) % MOD;
  rep(i, N) {
    T[i] = (1LL * pB[i] * S[i]) % MOD;
    if (i > 0)
      T[i] = (T[i] + T[i - 1]) % MOD;
  }

  bool same = true;
  rep(i, N - 1) if (S[i] != S[i + 1]) same = false;
  if (same) {
    cout << N << "\n";
    cout << 1 << "\n";
    return 0;
  }
  if (is_good(0, N - 1)) {
    cout << 1 << "\n";
    cout << 1 << "\n";
    return 0;
  }
  rep(i, N) if (is_good(0, i)) good_prefix[i] = true;
  rep(i, N) if (is_good(N - 1 - i, N - 1)) good_suffix[i] = true;
  int s = 0;
  for (int p = 1; p <= N - 1; p++) {
    if (good_prefix[p - 1] && good_suffix[N - 1 - p])
      s++;
  }
  cout << 2 << "\n";
  cout << s << "\n";
  return 0;
}


Fixed submission:
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <vector>
using namespace std;

typedef pair<int, int> P;
#define rep(i, n) for (int i = 0; i < (n); i++)
#define all(c) (c).begin(), (c).end()
#define uniq(c) c.erase(unique(all(c)), (c).end())
#define index(xs, x) (int)(lower_bound(all(xs), x) - xs.begin())
#define _1 first
#define _2 second
#define pb push_back
#define INF 1145141919
#define MOD 1000000007

const int B = 321;
int N;
string S;
int dp[500001];
int num[500001];
int T[500001];
int pB[500001];
bool good_prefix[500000], good_suffix[500000];

inline int rhash(int l, int r) {
  return (1LL * ((T[r] + MOD - (l > 0 ? T[l - 1] : 0)) % MOD) * pB[N - l]) %
         MOD;
}

bool cycle(int l, int r, int d) {
  if (2 * d > r - l + 1)
    return false;
  // [l, r-d] = [l+d, r]
  return rhash(l, r - d) == rhash(l + d, r);
}

bool is_good(int l, int r) {
  int n = r - l + 1;
  int til = sqrt(n);
  for (int d = 1; d <= til; d++) {
    if (n % d)
      continue;
    if (cycle(l, r, d))
      return false;
    if (cycle(l, r, n / d))
      return false;
  }
  return true;
}

signed main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cin >> S;
  N = S.length();
  pB[0] = 1;
  for (int i = 1; i <= 500000; i++)
    pB[i] = (1LL * pB[i - 1] * B) % MOD;
  rep(i, N) {
    T[i] = (1LL * pB[i] * S[i]) % MOD;
    if (i > 0)
      T[i] = (T[i] + T[i - 1]) % MOD;
  }

  bool same = true;
  rep(i, N - 1) if (S[i] != S[i + 1]) same = false;
  if (same) {
    cout << N << "\n";
    cout << 1 << "\n";
    return 0;
  }
  if (is_good(0, N - 1)) {
    cout << 1 << "\n";
    cout << 1 << "\n";
    return 0;
  }
  rep(i, N) if (is_good(0, i)) good_prefix[i] = true;
  rep(i, N) if (is_good(N - 1 - i, N - 1)) good_suffix[i] = true;
  int s = 0;
  for (int p = 1; p <= N - 1; p++) {
    if (good_prefix[p - 1] && good_suffix[N - 1 - p])
      s++;
  }
  cout << 2 << "\n";
  cout << s << "\n";
  return 0;
}