//#define _GLIBCXX_DEBUG
#include <bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<b;i++)
#define rep(i,n) FOR(i,0,n)
#define ROF(i,a,b) for(int i=a;i>=b;i--)
#define per(i,a) ROF(i,a,0)
#define pb push_back
using namespace std;
using ll=long long;
using ld=long double;
typedef pair<ll,ll> P;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<P> vP;
typedef vector<char> vc;
typedef vector<vc> vvc;
const ll MOD=1000000007;
const ll MOD2=998244353;
const ld PI=acos(-1);
const ll INF=1e18;
struct edge{ll to,cost;};
struct edge2{ll from,to,cost;};

template <typename T>
bool chmax(T &a, const T& b) {
    if (a < b) {
      a = b;
        return true;
    }
    return false;
}

template <typename T>
bool chmin(T &a, const T& b) {
    if (a > b) {
      a = b;
      return true;
    }
    return false;
}

//https://qiita.com/keymoon/items/11fac5627672a6d6a9f6から

class Rollinghash{
    ll MASK30 = (1LL << 30) - 1;
    ll MASK31 = (1LL << 31) - 1;
    ll MD = (1LL << 61) - 1;
    ll MASK61 = MD;
    ll base=0;

    //a*b mod 2^61-1を返す関数(最後にModを取る)
    ll Mul(ll a, ll b){
        ll au = a >> 31;
        ll ad = a & MASK31;
        ll bu = b >> 31;
        ll bd = b & MASK31;
        ll mid = ad * bu + au * bd;
        ll midu = mid >> 30;
        ll midd = mid & MASK30;
        return CalcMod(au * bu * 2 + midu + (midd << 31) + ad * bd);
    }

    //mod 2^61-1を計算する関数
    ll CalcMod(ll x)
    {
        ll xu = x >> 61;
        ll xd = x & MASK61;
        ll res = xu + xd;
        if (res >= MD) res -= MD;
        return res;
    }
    static inline ll generate_base() {
        mt19937_64 mt(chrono::steady_clock::now().time_since_epoch().count());
        uniform_int_distribution<ll> rand(2,(1LL<<61)-3);
        return rand(mt);
    }
    vl hash,power;

public:
    Rollinghash(string &s){//型名は必要に応じて変える(string,vlなど)
        if(base==0){
            base=generate_base();
        }
        ll n=s.size();
        hash.assign(n+1, 0);
        power.assign(n+1, 1);
        rep(i,n){
            power[i+1]=Mul(power[i], base)%MD;
            hash[i+1]=(Mul(hash[i], base)+s[i])%MD;
        }
    }
    ll get(int l, int r){
        return (hash[r]+MD-Mul(hash[l], power[r-l])%MD)%MD;
    }
    int LCP(int l0, int r0, int l1, int r1){
        int ok = 0,ng = min(r0 - l0, r1 - l1) + 1;
        while(abs(ok - ng) > 1){
            int rh_mid = (ok+ng)/2;
            if(get(l0, l0+rh_mid) == get(l1, l1+rh_mid)) ok=rh_mid;
            else ng = rh_mid;
        }
        return ok;
    }
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int N;
    string S;
    cin >> N >> S;
    Rollinghash rh(S);
    auto judge = [&](int d){
        map<int,int> mp;
        rep(i,N-d+1){
            int v=rh.get(i,i+d);
            if(mp.count(v)){
                if(i-mp[v]>=d)return true;
            }
            else{
                mp[v]=i;
            }
        }
        return false;
    };
    int OK=0,NG=N/2+1;
    while(abs(OK-NG)>1){
        int mid=(OK+NG)/2;
        if(judge(mid)){
            OK=mid;
        }
        else{
            NG=mid;
        }
    }
    cout << OK << endl;
}
/*
overflow checked?
corner case checked?
boundary checked?
not TLE in worst case checked?
*/


Measured memory_bytes: 3924