Problem p01863 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define REP(i, n) for (int i = 0; i < (int)(n); ++i)
#define DEBUG(x) cerr << #x << " = " << x << endl
int BASE = 131;
int MOD = 3037000493;

int powMod(int x, int y) {
  int res = 1;
  for (; y > 0; y >>= 1, (x *= x) %= MOD) {
    if (y & 1)
      (res *= x) %= MOD;
  }
  return res;
}

int subMod(int x, int y) {
  x %= MOD;
  y %= MOD;
  if (x < 0)
    x += MOD;
  if (y < 0)
    y += MOD;
  int res = x - y;
  if (res < 0)
    res += MOD;
  return res % MOD;
}

int partial(const vector<int> &hashary, int i, int j) {
  // cerr << "(" << i << "," << j << ") = ";
  int sub = hashary[i] * powMod(BASE, j - i);
  sub %= MOD;
  if (sub < 0)
    sub += MOD;
  // cerr << hashary[j] << " - " << sub << " = " << subMod(hashary[j], sub) <<
  // endl;
  return subMod(hashary[j], sub);
}

signed main() {
  ios::sync_with_stdio(false);
  string S;
  cin >> S;
  vector<int> hashary(S.size() + 1, 0);
  REP(i, S.size()) { hashary[i + 1] = (hashary[i] * BASE + S[i]) % MOD; }

  bool flag = false;
  string strA, strB;
  REP(i, S.size()) {
    int A = i + 1;
    if (((int)S.size() - 3 * A) % 2 != 0)
      continue;
    int B = ((int)S.size() - 3 * A) / 2;
    if (B < 1)
      continue;
    // DEBUG(A);
    // DEBUG(B);
    if (partial(hashary, 0, A) == partial(hashary, A + B, A + B + A) &&
        partial(hashary, 0, A) ==
            partial(hashary, A + B + A + B, A + B + A + B + A) &&
        partial(hashary, A, A + B) ==
            partial(hashary, A + B + A, A + B + A + B)) {
      if (flag == false) {
        flag = true;
        strA = S.substr(0, A);
        strB = S.substr(A, B);
      } else {
        if (strA.size() + strB.size() > A + B) {
          strA = S.substr(0, A);
          strB = S.substr(A, B);
        }
      }
    }
  }
  if (!flag) {
    cout << "mitomerarenaiWA" << endl;
  } else {
    cout << "Love " << strA << strB << "!" << endl;
  }
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define DEBUG(x) cerr << #x << " = " << x << endl
#define REP(i, n) for (int i = 0; i < (int)(n); ++i)

const int INF = (int)1e18;
struct RMQ {
  vector<int> data;
  int N;
  RMQ(int size) {
    N = 1;
    while (N < size)
      N *= 2;
    data.assign(2 * N - 1, INF);
  }
  void update(int k, int a) {
    k += N - 1;
    data[k] = a;
    while (k > 0) {
      k = (k - 1) / 2;
      data[k] = min(data[2 * k + 1], data[2 * k + 2]);
    }
  }
  int minimum(int a, int b) { return minimum_sub(a, b, 0, 0, N); }
  int minimum_sub(int a, int b, int k, int l, int r) {
    if (r <= a || b <= l)
      return INF;
    if (a <= l && r <= b)
      return data[k];

    return min(minimum_sub(a, b, 2 * k + 1, l, (l + r) / 2),
               minimum_sub(a, b, 2 * k + 2, (l + r) / 2, r));
  }
};

struct SuffixArray {
  int n, k;
  vector<int> sa, rsa, lcp, rank, tmp;
  SuffixArray(const string &S)
      : n(S.size()), sa(S.size() + 1), rsa(S.size() + 1), lcp(S.size() + 1),
        rank(S.size() + 1), tmp(S.size() + 1) {
    {
      auto compare_sa = [&](int i, int j) -> bool {
        if (rank[i] != rank[j])
          return rank[i] < rank[j];
        else {
          int ri = i + k <= n ? rank[i + k] : -1;
          int rj = j + k <= n ? rank[j + k] : -1;
          return ri < rj;
        }
      };
      for (int i = 0; i <= n; ++i) {
        sa[i] = i;
        rank[i] = i < n ? S[i] : -1;
      }
      for (k = 1; k <= n; k *= 2) {
        sort(sa.begin(), sa.begin() + n + 1, compare_sa);
        tmp[sa[0]] = 0;
        for (int i = 1; i <= n; i++) {
          tmp[sa[i]] = tmp[sa[i - 1]] + (compare_sa(sa[i - 1], sa[i]) ? 1 : 0);
        }
        for (int i = 0; i <= n; i++) {
          rank[i] = tmp[i];
        }
      }
    }
    {
      for (int i = 0; i <= n; i++)
        rank[sa[i]] = i;
      int h = 0;
      lcp[0] = 0;
      for (int i = 0; i < n; i++) {
        int j = sa[rank[i] - 1];
        if (h > 0)
          h--;
        for (; j + h < n && i + h < n; h++) {
          if (S[j + h] != S[i + h])
            break;
        }
        lcp[rank[i] - 1] = h;
      }
    }
    {
      for (int i = 0; i <= n; ++i) {
        rsa[sa[i]] = i;
      }
    }
  }
};

char CS[1000001];

signed main() {
  scanf("%s", CS);
  string S(CS);
  int N = S.size();
  SuffixArray SA(S);
  RMQ rmq(N + 1);
  REP(i, N + 1) { rmq.update(i, SA.lcp[i]); }
  int ansA = INF, ansB = INF;
  REP(i, N / 2) {
    int LA = i + 1;
    int LB = (N - 3 * LA) / 2;
    if (LB < 1)
      break;
    int l, r;

    l = SA.rsa[0], r = SA.rsa[N - i - 1];
    if (l > r)
      swap(l, r);
    int lcpA = rmq.minimum(l, r);

    l = SA.rsa[LA], r = SA.rsa[LA + LB + LA];
    if (l > r)
      swap(l, r);
    int lcpB = rmq.minimum(l, r);
    // DEBUG(LA);
    // DEBUG(lcpA);
    // DEBUG(LB);
    // DEBUG(lcpB);
    if (lcpA >= LA && lcpB >= LB) {
      if (LA + LB < ansA + ansB) {
        ansA = LA;
        ansB = LB;
      }
    }
  }
  if (ansA == INF && ansB == INF) {
    cout << "mitomerarenaiWA" << endl;
  } else {
    cout << "Love " << S.substr(0, ansA) << S.substr(ansA, ansB) << "!" << endl;
  }
}