#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using vl = vector<ll>;
template<class T> using vc = vector<T>;
template<class T> using vvc = vector<vector<T>>;

const ll MOD = 1e9 + 7;
// const ll MOD = 998244353;
const ll INF = 1e16;
const ld EPS = 1e-11;
const ld PI = acos(-1.0L);
#define eb emplace_back
#define all(x) (x).begin(), (x).end()
#define rep(i, n) for (ll i = 0; i < (n); i++)
#define repr(i, n) for (ll i = (n)-1; i >= 0; i--)
#define repe(i, l, r) for (ll i = (l); i < (r); i++)
#define reper(i, l, r) for (ll i = (r)-1; i >= (l); i--)

template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0; }

#ifdef DEBUG
template <class T, class N> void verr(const T& a, const N& n) { rep(i, n) cout << a[i] << " "; cout << "\n"; }
template<class T> void verr(const vector<T>& v){ for(auto& a : v) cout << a << " "; cout << "\n"; }
ll dbgt = 1; void err() { cout << "passed " << dbgt++ << "\n"; }
template<class H, class... T> void err(H&& h,T&&... t){ cout<< h << (sizeof...(t)?" ":"\n"); if(sizeof...(t)>0) err(forward<T>(t)...); }
#endif

void init() {cin.tie(0);ios::sync_with_stdio(false);cout << fixed << setprecision(15);}
//--------------------------------------------------------------------------------//

// struct rolling_hash{
//     using ull = unsigned long long;
//     const ull mod = (1ll << 61) - 1, mask30 = (1ll << 30) - 1, mask31 = (1ll << 31) - 1, mask61 = (1ll << 61) - 1;
//     const ull base[2] = {1007, 2009}, positiviser = mod * 5;
//     ull sn;
//     vector<ull> hash[2], power[2];

//     rolling_hash(){}
//     rolling_hash(const string& s){
//         sn = s.size();
//         for (int bi = 0; bi < 2; bi++) {
//             hash[bi].assign(sn + 1, 0);
//             power[bi].assign(sn + 1, 0);
//             power[bi][0] = 1;
//             for (int i = 0;i < sn;i++){
//                 power[bi][i + 1] = calc_mod(mul(power[bi][i], base[bi]));
//                 hash[bi][i + 1] = calc_mod(mul(hash[bi][i], base[bi]) + s[i]);
//             }
//         }
//     }

//     inline ull mul(ull a, ull b){
//         ull au = a >> 31, ad = a & mask31;
//         ull bu = b >> 31, bd = b & mask31;
//         ull mid = ad * bu + au * bd;

//         return ((au * bu) << 1) + ad * bd + ((mid & mask30) << 31) + (mid >> 30);
//     }
    
//     inline ull calc_mod(ull a){
//         a = (a & mod) + (a >> 61);
//         if (a >= mod) a -= mod;
//         return a;
//     }

//     // S[b1:b1+len], S[b2:b2+len]が同じか判定
//     inline bool match(int begin1, int begin2, int len){
//         ull res1_base0 = calc_mod(hash[0][begin1 + len] + positiviser - mul(hash[0][begin1], power[0][len]));
//         ull res1_base1 = calc_mod(hash[1][begin1 + len] + positiviser - mul(hash[1][begin1], power[1][len]));
//         ull res2_base0 = calc_mod(hash[0][begin2 + len] + positiviser - mul(hash[0][begin2], power[0][len]));
//         ull res2_base1 = calc_mod(hash[1][begin2 + len] + positiviser - mul(hash[1][begin2], power[1][len]));

//         return (res1_base0 == res2_base0) && (res1_base1 == res2_base1);
//     }
//     inline bool match(pair<ull,ull> p1, pair<ull,ull>p2){
//         return (p1.first == p2.first) && (p1.second == p2.second);
//     }

//     // S[b:b+len]のbase0,base1におけるハッシュをペアで返す
//     inline pair<ull,ull> get(int begin, int len){
//         ll b0 = calc_mod(hash[0][begin + len] + positiviser - mul(hash[0][begin], power[0][len]));
//         ll b1 = calc_mod(hash[1][begin + len] + positiviser - mul(hash[1][begin], power[1][len]));
//         return {b0, b1};
//     }
    
// };

using ull = unsigned long long;
struct RollingHash{
    const ull mod = (1ll << 61) - 1, mask30 = (1ll << 30) - 1, mask31 = (1ll << 31) - 1;
    const ull base = 1009, positiviser = mod * 5;
    ull sn;
    vector<ull> hash, power;

    RollingHash(){}
    RollingHash(const string& s){
        sn = s.size();
        hash.assign(sn + 1, 0);
        power.assign(sn + 1, 0);
        power[0] = 1;
        for (int i = 0;i < sn;i++){
            power[i + 1] = calc_mod(mul(power[i], base));
            hash[i + 1] = calc_mod(mul(hash[i], base) + s[i]);
        }
    }

    inline ull mul(ull a, ull b){
        ull au = a >> 31, ad = a & mask31;
        ull bu = b >> 31, bd = b & mask31;
        ull mid = ad * bu + au * bd;

        return ((au * bu) << 1) + ad * bd + ((mid & mask30) << 31) + (mid >> 30);
    }
    
    inline ull calc_mod(ull a){
        a = (a & mod) + (a >> 61);
        if (a >= mod) a -= mod;
        return a;
    }

    // S[b1:b1+len], S[b2:b2+len]が同じか判定
    inline bool match(int begin1, int begin2, int len){
        ull h1 = calc_mod(hash[begin1 + len] + positiviser - mul(hash[begin1], power[len]));
        ull h2 = calc_mod(hash[begin2 + len] + positiviser - mul(hash[begin2], power[len]));

        return h1 == h2;
    }
    inline bool match(pair<ull,ull> p1, pair<ull,ull>p2){
        return (p1.first == p2.first) && (p1.second == p2.second);
    }

    // S[b:b+len]のbase0,base1におけるハッシュを返す
    inline ull get(int begin, int len){
        return calc_mod(hash[begin + len] + positiviser - mul(hash[begin], power[len]));
    }
    
};

int main() {
    init();
    ll N;
    string s;
    cin >> N >> s;
    RollingHash rh(s);

    auto check = [&](ll d) -> bool {
        map<ull, ll> ma;
        rep(i,N-d+1){
            auto p = rh.get(i, d);
            if(ma.count(p)){
                if (i - ma[p] >= d) return true;
            }
            else
                ma[p] = i;
        }
        return false;
    };
    ll ok = 0, ng = N / 2 + 1;
    while(ng-ok>1){
        ll mid = (ok + ng) / 2;
        (check(mid) ? ok : ng) = mid;
    }
    cout << ok << endl;
}

Measured memory_bytes: 640