#include <bits/stdc++.h>
using namespace std;
namespace i207M {
template <class T>
inline void in(T &x) {
  x = 0;
  int f = 1;
  char c = getchar();
  while (c < '0' || c > '9') {
    if (c == '-') f = -1;
    c = getchar();
  }
  while (c >= '0' && c <= '9') x = x * 10 + (c ^ '0'), c = getchar();
  x *= f;
}
int n;
char s[400005];
int len[400005], fa[400005], ch[400005][26], tot = 1;
int pos[400005];
const int rt = 1;
int ins(int x, int w) {
  int np = ++tot;
  len[np] = len[x] + 1;
  while (x && !ch[x][w]) ch[x][w] = np, x = fa[x];
  if (!x)
    fa[np] = rt;
  else {
    if (len[ch[x][w]] == len[x] + 1)
      fa[np] = ch[x][w];
    else {
      int q = ch[x][w], nq = ++tot;
      len[nq] = len[x] + 1, fa[nq] = fa[q];
      pos[nq] = pos[q];
      for (register int i = 0; i < 26; ++i) ch[nq][i] = ch[q][i];
      fa[np] = fa[q] = nq;
      while (x && ch[x][w] == q) ch[x][w] = nq, x = fa[x];
    }
  }
  return np;
}
int tre[400005];
int cnt, sum[400005 * 30], ls[400005 * 30], rs[400005 * 30];
void ins(int &x, int l, int r, int p) {
  if (!x) x = ++cnt;
  ++sum[x];
  if (l == r) return;
  int mid((l + r) >> 1);
  if (p <= mid)
    ins(ls[x], l, mid, p);
  else
    ins(rs[x], mid + 1, r, p);
}
int merge(int a, int b, int l, int r) {
  if (!a || !b) return a | b;
  int x = ++cnt;
  sum[x] = sum[a] + sum[b];
  if (l == r) return x;
  int mid((l + r) >> 1);
  ls[x] = merge(ls[a], ls[b], l, mid);
  rs[x] = merge(rs[a], rs[b], mid + 1, r);
  return x;
}
int ask(int x, int l, int r, int ql, int qr) {
  if (!x) return 0;
  if (ql <= l && r <= qr) return sum[x];
  int mid((l + r) >> 1);
  int t = 0;
  if (ql <= mid) t = ask(ls[x], l, mid, ql, qr);
  if (qr > mid) t += ask(rs[x], mid + 1, r, ql, qr);
  return t;
}
vector<int> sn[400005];
void dfs(int x) {
  for (register int i = 0, v; i < (int)sn[x].size(); ++i) {
    v = sn[x][i];
    dfs(v);
    tre[x] = merge(tre[x], tre[v], 1, n);
  }
}
void prework() {
  int lst = rt;
  for (register int i = 1; i <= n; ++i)
    lst = ins(lst, s[i] - 'a'), ins(tre[lst], 1, n, i), pos[lst] = i;
  for (int i = 1; i <= tot; ++i) sn[fa[i]].push_back(i);
  dfs(rt);
}
int f[400005];
int fp[400005], nt[400005];
void efs(int x) {
  fp[x] = 1;
  if (x != rt) {
    if (fa[x] == rt)
      f[x] = 1;
    else {
      f[x] = f[fa[x]];
      int p = fp[fa[x]];
      while (p != x &&
             ask(tre[p], 1, n, pos[x] - len[x] + len[p], pos[x] - 1)) {
        f[x] = max(f[x], f[fp[x] = p] + 1);
        p = nt[p];
      }
    }
  }
  for (register int i = 0; i < (int)sn[x].size(); ++i)
    nt[x] = sn[x][i], efs(sn[x][i]);
}
signed main() {
  in(n);
  scanf("%s", s + 1);
  prework();
  efs(rt);
  int ans = 0;
  for (register int i = 1; i <= tot; ++i) ans = max(ans, f[i]);
  printf("%d", ans);
  return 0;
}
}  // namespace i207M
signed main() {
  i207M::main();
  return 0;
}
