/*#pragma GCC optimize("Ofast,no-stack-protector")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("fast-math")*/
#include <iostream>
#include <complex>
#include <vector>
#include <string>
#include <algorithm>
#include <cstdio>
#include <numeric>
#include <cstring>
#include <ctime>
#include <cstdlib>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <list>
#include <cmath>
#include <bitset>
#include <cassert>
#include <queue>
#include <stack>
#include <deque>
#include <random>

using namespace std;

#define pb push_back
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define Str(x) to_string(x)
#define len(s) (int)s.size()
#define int long long
typedef long long ll;
typedef long double lld;
typedef string str;
typedef unsigned long long ull;

const int mod1 = 1e9 + 7, mod2 = 1e9 + 17, base = 41;

void build(string s, vector<pair<int, int>> &step, vector<pair<int, int> > &hs) {
    int n = len(s);
    step.resize(n+1);
    hs.resize(n + 1);
    step[0] = {1, 1};
    hs[0] = {0, 0};
    for (int i = 0; i < n; i++) {
        step[i + 1].first = step[i].first * base % mod1;
        step[i + 1].second = step[i].second * base % mod2;
        hs[i + 1].first = (hs[i].first * base + s[i]) % mod1;
        hs[i + 1].second = (hs[i].second * base + s[i]) % mod2;
    }
}

pair<int, int> get(vector<pair<int, int>> &step, vector<pair<int, int> > &hs, int i, int j) {
    int first = ((hs[j + 1].first - hs[i].first * step[j - i + 1].first) % mod1 + mod1) % mod1;
    int second = ((hs[j + 1].second - hs[i].second * step[j - i + 1].second) % mod2 + mod2) % mod2;
    return {first, second};
}

bool check(vector<pair<int, int>> &step, vector<pair<int, int> > &hs, int ln)
{
    //cout << ln << endl;
    vector <pair<pair<int, int>, int> > v; // hash, index;
    for (int i = 0; i + ln < len(step); i++)
    {
        pair <int, int> q = get(step, hs, i, i + ln - 1);
        //cout << q.first << " " << q.second << endl;
        v.pb({get(step, hs, i, i + ln - 1), i});
    }
    stable_sort(all(v));
    int ind = v[0].second;
    /*for (auto it : v)
    {
        cout << it.first.first << " " << it.first.second << " " << it.second << endl;
    }*/
    for (int i = 1; i < len(v); i++)
    {
        if (v[i].first != v[i-1].first)
        {
            int KEKEOS = v[i-1].second;
            if (ind + ln <= KEKEOS)
            {
                return true;
            }
            ind = v[i].second;
        }
    }
    int KEKEOS = v.back().second;
    if (ind + ln <= KEKEOS)
    {
        return true;
    }
    return false;
}

main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
#ifdef LOCAL
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
    int n;
    string s;
    cin >> n >> s;
    int l = 1, r = n, ans = 0;
    vector <pair<int, int> > hs, step;
    build(s, step, hs);
    while (l <= r) {
        int m = (l + r) / 2;
        if (check(step, hs, m))
        {
            ans = m;
            l = m + 1;
        }
        else
        {
            r = m - 1;
        }
    }
    cout << ans;

    return 0;
}

Measured memory_bytes: 800