#include <bits/stdc++.h>
using namespace std;
const int N = 402000;
struct newn {
  int ls, rs;
} d[N * 20];
int rt[N], n, dp[N];
struct SEG {
  int tot;
  void modify(int &k, int l, int r, int x) {
    if (!k) k = ++tot;
    if (l == r) return;
    int mid = l + r >> 1;
    if (x <= mid)
      modify(d[k].ls, l, mid, x);
    else
      modify(d[k].rs, mid + 1, r, x);
  }
  int mrge(int k1, int k2, int l, int r) {
    if (!k1 || !k2) return k1 | k2;
    int now = ++tot;
    if (l == r) return now;
    int mid = l + r >> 1;
    d[now].ls = mrge(d[k1].ls, d[k2].ls, l, mid);
    d[now].rs = mrge(d[k1].rs, d[k2].rs, mid + 1, r);
    return now;
  }
  bool query(int k, int l, int r, int x, int y) {
    if (!k || l > y || r < x) return 0;
    if (l >= x && r <= y) return 1;
    int mid = l + r >> 1;
    if (query(d[k].ls, l, mid, x, y)) return 1;
    if (query(d[k].rs, mid + 1, r, x, y)) return 1;
    return 0;
  }
} seg;
int ans;
struct Edge {
  int nxt, to;
} e[N];
int fr[N], h[N], e_num;
void add(int from, int to) {
  e[++e_num] = (Edge){h[from], to};
  h[from] = e_num;
}
struct SAM {
  int tar[N][26], tot = 1, lst = 1, len[N], pos[N], pre[N];
  int node(int l) {
    len[++tot] = l;
    return tot;
  }
  void ins(int c, int p) {
    int i = lst;
    lst = node(len[i] + 1);
    pos[lst] = p;
    seg.modify(rt[lst], 1, n, pos[lst]);
    while (!tar[i][c]) {
      tar[i][c] = lst;
      if (!(i = pre[i])) return void(pre[lst] = 1);
    }
    int rtm = tar[i][c];
    if (len[rtm] == len[i] + 1) return void(pre[lst] = rtm);
    int gnn = node(len[i] + 1);
    pos[gnn] = pos[rtm];
    memcpy(tar[gnn], tar[rtm], sizeof(tar[0]));
    pre[gnn] = pre[rtm];
    pre[lst] = pre[rtm] = gnn;
    do {
      tar[i][c] = gnn;
      i = pre[i];
    } while (i && tar[i][c] == rtm);
  }
  void dfs1(int u) {
    for (int i = h[u]; i; i = e[i].nxt) {
      int v = e[i].to;
      dfs1(v);
      rt[u] = seg.mrge(rt[u], rt[v], 1, n);
    }
  }
  void dfs2(int u) {
    for (int i = h[u]; i; i = e[i].nxt) {
      int v = e[i].to;
      if (u != 1) {
        if (seg.query(rt[fr[u]], 1, n, pos[v] - len[v] + len[fr[u]],
                      pos[v] - 1))
          fr[v] = v, dp[v] = dp[u] + 1;
        else
          dp[v] = dp[u], fr[v] = fr[u];
      } else
        dp[v] = 1, fr[v] = v;
      dfs2(v);
    }
    ans = max(ans, dp[u]);
  }
  void solve() {
    for (int i = 2; i <= tot; i++) add(pre[i], i);
    dfs1(1);
    dfs2(1);
  }
} sam;
char s[N >> 1];
int main() {
  scanf("%d", &n);
  scanf("%s", s + 1);
  for (int i = 1; i <= n; i++) sam.ins(s[i] - 'a', i);
  sam.solve();
  printf("%d", ans);
}
