#include <bits/stdc++.h>
const int N = 2e5 + 50;
int n;
char s[N];
namespace Seg {
const int SZ = 2 * N * 20;
int top, root[SZ];
int ls[SZ], rs[SZ];
void init(int &u, int L, int R, int pos) {
  if (!u) u = ++top;
  if (L == R) return;
  int mid = L + R >> 1;
  if (pos <= mid)
    init(ls[u], L, mid, pos);
  else
    init(rs[u], mid + 1, R, pos);
}
void init(int u, int pos) { init(root[u], 1, n, pos); }
int mergeNode(int u, int v) {
  if (!u || !v) return u + v;
  int x = ++top;
  ls[x] = mergeNode(ls[u], ls[v]);
  rs[x] = mergeNode(rs[u], rs[v]);
  return x;
}
void merge(int u, int v) { root[u] = mergeNode(root[u], root[v]); }
bool find(int u, int L, int R, int l, int r) {
  if (!u) return false;
  if (L == l && R == r) return true;
  int mid = L + R >> 1;
  bool rtn = false;
  if (l <= mid) rtn |= find(ls[u], L, mid, l, std::min(mid, r));
  if (r > mid) rtn |= find(rs[u], mid + 1, R, std::max(mid + 1, l), r);
  return rtn;
}
bool find(int u, int l, int r) {
  if (l > r) return false;
  return find(root[u], 1, n, l, r);
}
}  // namespace Seg
struct Sam {
  static const int SZ = N << 1;
  int top, last;
  int ch[SZ][26], fa[SZ], mx[SZ], rp[SZ];
  int buc[N], order[SZ];
  int pre[SZ], f[SZ];
  Sam() : top(1), last(1) {}
  void extend(char c, int pos) {
    int x = c - 'a', p = last;
    int np = last = ++top;
    Seg::init(np, pos);
    mx[np] = mx[p] + 1;
    rp[np] = pos;
    for (; p && !ch[p][x]; p = fa[p]) {
      ch[p][x] = np;
    }
    if (!p) {
      fa[np] = 1;
      return;
    }
    int q = ch[p][x];
    if (mx[q] == mx[p] + 1) {
      fa[np] = q;
      return;
    }
    int nq = ++top;
    mx[nq] = mx[p] + 1;
    fa[nq] = fa[q];
    fa[q] = fa[np] = nq;
    memcpy(ch[nq], ch[q], sizeof ch[nq]);
    for (; ch[p][x] == q; p = fa[p]) ch[p][x] = nq;
  }
  void sort() {
    for (int i = 1; i <= top; i++) buc[mx[i]]++;
    for (int i = 1; i <= top; i++) buc[i] += buc[i - 1];
    for (int i = 1; i <= top; i++) order[buc[mx[i]]--] = i;
  }
  void init() {
    sort();
    for (int i = top; i >= 2; i--) {
      int u = order[i];
      Seg::merge(fa[u], u);
      rp[fa[u]] = rp[u];
    }
  }
  int dp() {
    int ans = 0;
    pre[1] = 1;
    for (int i = 2; i <= top; i++) {
      int u = order[i], v = pre[fa[u]];
      if (v == 1 || Seg::find(v, rp[u] - mx[u] + mx[v], rp[u] - 1)) {
        f[u] = f[fa[u]] + 1;
        pre[u] = u;
      } else {
        f[u] = f[fa[u]];
        pre[u] = v;
      }
      ans = std::max(ans, f[u]);
    }
    return ans;
  }
} sam;
int main() {
  scanf("%d%s", &n, s + 1);
  n = strlen(s + 1);
  for (int i = 1; i <= n; i++) {
    sam.extend(s[i], i);
  }
  sam.init();
  printf("%d\n", sam.dp());
  return 0;
}
