#include <bits/stdc++.h>
using namespace std;

#define Mset(s, n)      memset(s, n, sizeof(s))
#define Rp0(i, m)       for(int i = 0; i < m; ++i)
#define Rpd(i, m, l)    for(int i = l; i >= m; --i)
#define Rp1(i ,m)       for(int i = 1; i <= m; i++)
#define All(a)          (a).begin(), (a).end()
#define Lwb             lower_bound
#define Upb             upper_bound
#define Sz(a)           int((a).size())
#define u_map           unordered_map
#define Exist(a, b)     (find(All(a), (b)) != (a).end())
#define Sort(x)         sort(All(x))
#define Gsort(x)        sort(All(x), greater<typeof(*((x).begin()))>())
#define Unique(v)       Sort(v); (v).resize(unique(ALL(v)) - (v).begin())

#define fi              first
#define se              second
#define pb              push_back
#define pf              push_front
#define is              insert
#define ooi             INT_MAX
#define ool             LLONG_MAX
#define ll              long long
#define ull             unsigned ll
#define ld              long double
#define pii             pair<int, int>
#define vi              vector<int>
#define vpii            vector<pii>

const ll MOD = (ll) 1e9 + 7;
const ld PI = acos((ld) -1);
inline int Get_bit(int x, int k){return (x >> (k - 1)) & 1;}
inline ll Gcd(ll a, ll b) {ll r; while(b){ r = a % b; a = b; b = r;} return a;}
inline ll Lcm(ll a, ll b) {return a / Gcd(a, b) * b;}
inline ll Pow(ll n, ll k) {ll r = 1; for(; k; k >>= 1, n = n * n % MOD){if(k & 1) r = r * n % MOD;} return r;}


const int N = 5e3 + 10;

struct RollingHash {
    static const int base1 = 1007, base2 = 2009;
    static const int mod1 = 1000000007, mod2 = 1000000009;
    vector<long long> hash1, hash2, power1, power2;

    // construct
    RollingHash(const string &S) {
        int n = (int)S.size();
        hash1.assign(n, 0);
        hash2.assign(n, 0);
        power1.assign(n, 1);
        power2.assign(n, 1);
        for(int i = 1; i < n; ++i) {
            hash1[i] = (hash1[i - 1] * base1 + S[i]) % mod1;
            hash2[i] = (hash2[i - 1] * base2 + S[i]) % mod2;
            power1[i] = (power1[i - 1] * base1) % mod1;
            power2[i] = (power2[i - 1] * base2) % mod2;
        }
    }

    // get hash of S[left:right]
    inline pair<long long, long long> Get(int l, int r) const {
        long long res1 = hash1[r] - hash1[l - 1] * power1[r - l + 1] % mod1;
        if (res1 < 0) res1 += mod1;
        long long res2 = hash2[r] - hash2[l - 1] * power2[r - l + 1] % mod2;
        if (res2 < 0) res2 += mod2;
        return {res1, res2};
    }
};

int n, m, k, q, ans;

void Solve(){
    string s;
    cin >> n >> s;
    s = ' ' + s;
    RollingHash rh(s);

    auto Check = [&](int k) -> bool{
        map<pair<ll, ll>, int> mp;
        for(int i = 1; i <= n - k + 1; i++){
            pair<ll, ll> x = rh.Get(i, i + k - 1);
            if(!mp.count(x)){
                mp[x] = i + k - 1;
            } else if(mp[x] < i){
                return true;
            }
        }
        return false;
    };
    int left = 0, right = n / 2 + 1;
    while(right - left > 1){
        int mid = (left + right) >> 1;
        if(Check(mid)){
            left = mid;
        } else{
            right = mid;
        }
    }
    cout << left;
}

int main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cout << fixed << setprecision(10);
    Solve();
}

Measured memory_bytes: 768