Problem p02913 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <algorithm>
#include <cstring>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <tuple>
#include <vector>

#define FOR0(var, max) for (ul(var) = 0; (var) < (max); ++(var))
#define FORi(var, min, max) for (ul(var) = (min); (var) < (max); ++(var))
#define FORi_INV(var, min, max)                                                \
  for (ul(var) = (max)-1; (var) + 1 > (min); --(var))
#define FORITER(var, iter)                                                     \
  for (auto(iter) = (var).begin(); (iter) != (var).end(); (iter)++)
#define FORITER_INV(var, iter)                                                 \
  for (auto(iter) = (var).rbegin(); (iter) != (var).rend(); (iter)++)

#define LTLT(a, b, c) (((a) < (b)) && ((b) < (c)))
#define LELT(a, b, c) (((a) <= (b)) && ((b) < (c)))
#define LTLE(a, b, c) (((a) < (b)) && ((b) <= (c)))
#define LELE(a, b, c) (((a) <= (b)) && ((b) <= (c)))

using namespace std;

using uc = unsigned char;
using ui = unsigned int;
using ul = unsigned long long int;

using sc = signed char;
using si = signed int;
using sl = signed long long int;

const static ui NMAX = 5000;
static ui N;
static string S;

struct Z_algorithm {
  vector<ul> Z;

  Z_algorithm(const string &str) {
    ul n = str.size();
    Z.resize(n, 0);
    ul c = 0;
    FORi(i, 1, n) {
      if (Z[i - c] + i < Z[c] + c) {
        Z[i] = Z[i - c];
      } else {
        ul j = 0;
        if (i < c + Z[c]) {
          j = c + Z[c] - i;
        }
        while (i + j < n && str[i + j] == str[j]) {
          j++;
        }
        Z[i] = j;
        c = i;
      }
    }
  }
};

void solve(void) {
  ul res = 0;
  FOR0(i, N) {
    Z_algorithm z(S.substr(i));
    FOR0(j, S.substr(i).size()) {
      ul k = z.Z[j];
      if (k > j) {
        k = j;
      }
      res = max(k, res);
    }
  }
  cout << res << endl;
}

int main(void) {
  cin >> N;
  cin >> S;
  solve();
  return 0;
}

Fixed submission:
#include <algorithm>
#include <cstring>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <tuple>
#include <vector>

#define FOR0(var, max) for (ul(var) = 0; (var) < (max); ++(var))
#define FORi(var, min, max) for (ul(var) = (min); (var) < (max); ++(var))
#define FORi_INV(var, min, max)                                                \
  for (ul(var) = (max)-1; (var) + 1 > (min); --(var))
#define FORITER(var, iter)                                                     \
  for (auto(iter) = (var).begin(); (iter) != (var).end(); (iter)++)
#define FORITER_INV(var, iter)                                                 \
  for (auto(iter) = (var).rbegin(); (iter) != (var).rend(); (iter)++)

#define LTLT(a, b, c) (((a) < (b)) && ((b) < (c)))
#define LELT(a, b, c) (((a) <= (b)) && ((b) < (c)))
#define LTLE(a, b, c) (((a) < (b)) && ((b) <= (c)))
#define LELE(a, b, c) (((a) <= (b)) && ((b) <= (c)))

using namespace std;

using uc = unsigned char;
using ui = unsigned int;
using ul = unsigned long long int;

using sc = signed char;
using si = signed int;
using sl = signed long long int;

const static ui NMAX = 5000;
static ui N;
static string S;

struct Z_algorithm {
  vector<ul> Z;

  Z_algorithm(const string &str) {
    ul n = str.size();
    Z.resize(n, 0);
    ul c = 0;
    FORi(i, 1, n) {
      if (Z[i - c] + i < Z[c] + c) {
        Z[i] = Z[i - c];
      } else {
        ul j = 0;
        if (i < c + Z[c]) {
          j = c + Z[c] - i;
        }
        while (i + j < n && str[i + j] == str[j]) {
          j++;
        }
        Z[i] = j;
        c = i;
      }
    }
  }
};

void solve(void) {
  ul res = 0;
  FOR0(i, N) {
    Z_algorithm z(S.substr(i));
    FOR0(j, N - i) {
      ul k = z.Z[j];
      if (k > j) {
        k = j;
      }
      res = max(k, res);
    }
  }
  cout << res << endl;
}

int main(void) {
  cin >> N;
  cin >> S;
  solve();
  return 0;
}