#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using pii = pair<int, int>;
using piii = pair<pair<int, int>, int>;
using pll = pair<ll, ll>;
using pli = pair<ll, int>;
using pil = pair<int, ll>;
using uint = unsigned int;
template <typename T>
using Graph = vector<vector<T>>;
const int MOD = 1e9 + 7;
const ld PI = acosl(-1);

struct RollingHash {
    static const ull mod1 = (1ULL << 61) - 1, mod2 = (1ULL << 31) - 1;
    static const ull base1 = 9733, base2 = 9973;
    static const ull p1 = mod1 * 3, p2 = mod2 * 2;

    int N;
    vector<ull> hash1, hash2, power1, power2;

    RollingHash(const string &S) {
        N = S.length();
        hash1.assign(N + 1, 0);
        hash2.assign(N + 1, 0);
        power1.assign(N + 1, 1);
        power2.assign(N + 1, 1);
        for (int i = 0; i < N; ++i) {
            hash1[i + 1] = calcmod1(mul1(hash1[i], base1) + S[i]);
            hash2[i + 1] = calcmod2(mul2(hash2[i], base2) + S[i]);
            power1[i + 1] = calcmod1(mul1(power1[i], base1));
            power2[i + 1] = calcmod2(mul2(power2[i], base2));
        }
    }

    inline ull mul1(ull a, ull b) {
        ull au = a >> 31, ad = a & mod2;
        ull bu = b >> 31, bd = b & mod2;
        ull c = au * bd + ad * bu;
        ull cu = c >> 30, cd = c & (mod2 >> 1);
        return 2 * au * bu + ad * bd + cu + (cd << 31);
    }

    inline ull mul2(ull a, ull b) {
        ull c = a * b;
        ull cu = c >> 31, cd = c & mod2;
        return cu + cd;
    }

    inline ull calcmod1(ull a) {
        ull au = a >> 61, ad = a & mod1;
        ull res = au + ad;
        if (res >= mod1)
            res -= mod1;
        return res;
    }

    inline ull calcmod2(ull a) {
        // hash2 + p2 - mul2 < 3 * mod2
        // maxrep = 2
        while (a >= mod2)
            a -= mod2;
        return a;
    }

    inline pair<ull, ull> get(int l, int r) {
        ull res1 = calcmod1(hash1[r] + p1 - mul1(hash1[l], power1[r - l]));
        ull res2 = calcmod2(hash2[r] + p2 - mul2(hash2[l], power2[r - l]));
        return {res1, res2};
    }

    inline vector<int> search(string &T) {
        vector<int> idx;
        int Tlen = T.length();
        if (Tlen > N)
            return idx;

        pair<ull, ull> t_hash = {0, 0};
        for (int i = 0; i < Tlen; ++i) {
            t_hash.first = calcmod1(mul1(t_hash.first, base1) + T[i]);
            t_hash.second = calcmod2(mul2(t_hash.second, base2) + T[i]);
        }

        for (int i = 0; i + Tlen <= N; ++i) {
            pair<ull, ull> s_hash = get(i, i + Tlen);
            if (s_hash == t_hash)
                idx.push_back(i);
        }

        return idx;
    }
};

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);

    int N;
    string S;
    cin >> N >> S;

    RollingHash rhs(S);

    auto isok = [&](int x) -> bool {
        map<pair<ull, ull>, int> mp;
        for (int i = 0; i + x <= N; ++i) {
            pair<ull, ull> s_hash = rhs.get(i, i + x);
            if (mp.find(s_hash) == mp.end())
                mp[s_hash] = i;
            else if (i - mp[s_hash] >= x)
                return true;
        }
        return false;
    };

    auto search = [&]() -> int {
        int ok = 0, ng = N / 2 + 1;
        while (abs(ok - ng) > 1) {
            int mid = (ok + ng) >> 1;
            (isok(mid) ? ok : ng) = mid;
        }
        return ok;
    };

    cout << search() << endl;

    return 0;
}


Measured memory_bytes: 768