//#include<bits/stdc++.h>
#include<iostream>
#include <cstring>
#include <cstdlib>

using namespace std;
typedef long long ll;
const int MAXN = 20005;

char s[MAXN];
int n, k;
int t1[MAXN], t2[MAXN], c[MAXN];
int _rank[MAXN], height[MAXN], sa[MAXN];

bool cmp(int *r, int a, int b, int l) { return r[a] == r[b] && r[a + l] == r[b + l]; }

void da(char str[], int sa[], int rank[], int height[], int n, int m) {
    n++;
    int i, j, p, *x = t1, *y = t2;
    for (i = 0; i < m; i++)c[i] = 0;
    for (i = 0; i < n; i++)c[x[i] = str[i]]++;
    for (i = 1; i < m; i++)c[i] += c[i - 1];
    for (i = n - 1; i >= 0; i--)sa[--c[x[i]]] = i;
    for (j = 1; j <= n; j <<= 1) {
        p = 0;
        for (i = n - j; i < n; i++)
            y[p++] = i;
        for (i = 0; i < n; i++)
            if (sa[i] >= j)
                y[p++] = sa[i] - j;
        for (i = 0; i < m; i++)c[i] = 0;
        for (i = 0; i < n; i++)c[x[y[i]]]++;
        for (i = 1; i < m; i++)c[i] += c[i - 1];
        for (i = n - 1; i >= 0; i--)
            sa[--c[x[y[i]]]] = y[i];
        std::swap(x, y);
        p = 1;
        x[sa[0]] = 0;
        for (i = 1; i < n; i++) x[sa[i]] = cmp(y, sa[i - 1], sa[i], j) ? p - 1 : p++;
        if (p >= n)break;
        m = p;
    }
    int k = 0;
    n--;
    for (i = 0; i <= n; i++)rank[sa[i]] = i;
    for (i = 0; i < n; i++) {
        if (k)k--;
        j = sa[rank[i] - 1];
        while (str[i + k] == str[j + k])k++;
        height[rank[i]] = k;
    }
}

typedef long long ll;
const ll mod = static_cast<const ll>(1e9 + 7);
const int maxn = static_cast<const int>(1e6 + 5);
#define base 131

ll po[maxn];
ll po1[maxn];

// 0 based, l, arr inclusive.
ll getHash(const ll _hash[], int l, int r) {
    return (_hash[r] - _hash[l - 1] * po[r - l + 1] % mod + mod) % mod;
}

ll getHash2(const ll _hash[], int l, int r) {
    return (_hash[r] - _hash[l - 1] * po1[r - l + 1] % mod + mod) % mod;
}

ll strHash[maxn];
ll strHash2[maxn];

void init() {
    po[0] = 1;
    for (int i = 1; i < maxn; ++i)
        po[i] = (po[i - 1] * base) % mod;
    po1[0] = 1;
    for (int i = 1; i < maxn; ++i)
        po1[i] = (po1[i - 1] * 97) % mod;
}

void initHash(const char *str, ll *_hash, int ba) {
    _hash[0] = str[0] - '0';
    for (int i = 1; str[i]; i++)
        _hash[i] = ((_hash[i - 1] * ba) % mod + str[i] - '0') % mod;
}

int getRepeatTimes(int l, int len) {
    int res = l;
    while (height[res] >= len && res <= n) res++;
    return res - l + 1;
}

/**
 * ÅÐ¶ÏÊÇ·ñÓÐ³€¶ÈÎªlenµÄÖØžŽkŽÎŒ°ÒÔÉÏµÄµÄ×ÓŽ®
 * @param len
 * @return
 */
bool repeatsMoreThanK(int len) {
    int cnt = 1;
    for (int i = 0; i + len - 1 < n; ++i) {
        ll baseHash = getHash(strHash, i, i + len - 1);
        ll baseHash2 = getHash2(strHash2, i, i + len - 1);
        cnt = 1;
        for (int j = i + len; j + len - 1 < n; ++j) {
            ll currHash = getHash(strHash, j, j + len - 1);
            ll currHash2 = getHash2(strHash2, j, j + len - 1);
            if (currHash == baseHash && baseHash2 == currHash2) {
                ++cnt;
                if (cnt >= k)
                    return true;
            }
        }
    }
    return false;
}

bool repeatsMoreThanK(int n, int k) {
    int maxi = -1, mini = 0x3f3f3f3f;
    for (int i = 1; i <= n; ++i) {
        if (height[i] < k)
            maxi = sa[i], mini = sa[i];
        else {
            maxi = max(maxi, max(sa[i], sa[i - 1]));
            mini = min(mini, min(sa[i], sa[i - 1]));
            if (maxi - mini >= k) return true;
        }
    }
    return false;
}


int main() {
    k = 2;
    scanf("%d", &n);
    scanf("%s", s);
    init();
    initHash(s, strHash, 131);
    initHash(s, strHash2, 97);
//    da(s, sa, _rank, height, n, 128);
    int ans = 0, l = 1, r = n;
    while (l <= r) {
        int mid = (l + r) >> 1;
        if (repeatsMoreThanK(mid))
            ans = mid, l = mid + 1;
        else
            r = mid - 1;
    }
    printf("%d\n", ans);
    return 0;
}



Measured memory_bytes: 19328