#include <bits/stdc++.h>
using namespace std;
inline int read() {
  int nm = 0;
  bool fh = true;
  char cw = getchar();
  for (; !isdigit(cw); cw = getchar()) fh ^= (cw == '-');
  for (; isdigit(cw); cw = getchar()) nm = nm * 10 + (cw - '0');
  return fh ? nm : -nm;
}
int n, rt[400200], pt;
char str[400200];
struct Seg {
  int ls[400200 << 6], rs[400200 << 6];
  inline void ins(int x, int l, int r, int ps) {
    if (l == r) return;
    int mid = (l + r) >> 1;
    (ps <= mid) ? ins(ls[x] = ++pt, l, mid, ps)
                : ins(rs[x] = ++pt, mid + 1, r, ps);
  }
  inline int mg(int x, int y) {
    if (!x || !y) return x ^ y;
    int k = ++pt;
    ls[k] = mg(ls[x], ls[y]), rs[k] = mg(rs[x], rs[y]);
    return k;
  }
  inline bool qry(int x, int l, int r, int L, int R) {
    if (!x || L > R) return false;
    if (L <= l && r <= R) return true;
    int mid = (l + r) >> 1;
    bool flag = false;
    if (L <= mid) flag |= qry(ls[x], l, mid, L, R);
    if (R > mid) flag |= qry(rs[x], mid + 1, r, L, R);
    return flag;
  }
} P;
struct SAM {
  int len[400200], fa[400200], ed[400200], ch[400200][26], tot, last, root;
  int F[400200];
  inline int node(int x) {
    len[++tot] = x, fa[tot] = 0, memset(ch[tot], 0, sizeof(ch[tot]));
    return tot;
  }
  inline void extend(int c, int ps) {
    int p = last, np = node(len[p] + 1);
    ed[np] = ps;
    while (!ch[p][c]) ch[p][c] = np, p = fa[p];
    if (p == root && ch[p][c] == np)
      fa[p] = root;
    else {
      int q = ch[p][c];
      if (len[q] == len[p] + 1)
        fa[np] = q;
      else {
        int nq = node(len[p] + 1);
        fa[nq] = fa[q], ed[nq] = ed[q], fa[q] = fa[np] = nq,
        memcpy(ch[nq], ch[q], sizeof(ch[nq]));
        while (ch[p][c] == q) ch[p][c] = nq, p = fa[p];
      }
    }
    last = np;
  }
  int to[400200], nt[400200], fs[400200], tmp, ord[400200], tim, up[400200][21];
  inline void link(int x, int y) {
    to[++tmp] = y, nt[tmp] = fs[x], fs[x] = tmp;
  }
  inline void dfs(int x) {
    ord[++tim] = x;
    if (ed[x]) P.ins(rt[x] = ++pt, 1, n, ed[x]);
    up[x][0] = fa[x];
    for (int k = 1; k <= 20; k++) up[x][k] = up[up[x][k - 1]][k - 1];
    for (int i = fs[x]; i; i = nt[i])
      dfs(to[i]), rt[x] = P.mg(rt[x], rt[to[i]]);
  }
  inline void build() {
    tot = -1, last = root = node(0);
    for (int i = 1; i <= n; i++) extend(str[i] - 'a', i);
    for (int i = 1; i <= tot; i++) link(fa[i], i);
    dfs(0);
  }
  inline int solve() {
    int ans = 0;
    for (int i = 1; i <= tim; i++) {
      int x = ord[i], y = x, l = ed[x] - len[x] + 1, r = ed[x];
      if (!x) continue;
      F[x] = 1;
      while (fa[y]) {
        y = fa[y];
        assert(len[y] <= len[x]);
        if (P.qry(rt[y], 1, n, l + len[y] - 1, r - 1)) {
          F[x] = F[y] + 1;
          break;
        }
      }
      if (F[x] > ans) ans = F[x];
    }
    return ans;
  }
} S;
int main() {
  n = read(), scanf("%s", str + 1), S.build();
  printf("%d\n", S.solve());
  return 0;
}
