import std.stdio, std.string, std.conv;
import std.range, std.algorithm, std.array, std.typecons, std.container;
import std.math, std.numeric, std.random, core.bitop;

enum inf = 1_001_001_001;
enum inf6 = 1_001_001_001_001_001_001L;
enum mod = 1_000_000_007L;


void main() {
    int N;
    string S;
    scan(N);
    scan(S);

    auto rh = RollingHash(S);

    int ans;

    foreach (i ; 0 .. N) {
        foreach (j ; i .. N) {
            while (ans < j - i && j + ans < N && 
                rh.slice(i, i + ans + 1) == rh.slice(j, j + ans + 1)) ans++;
        }
    }

    writeln(ans);
}


struct RollingHash {
    enum MAX_LENGTH = 500000;
    enum ulong MASK30 = (1UL << 30) - 1;
    enum ulong MASK31 = (1UL << 31) - 1;
    enum ulong MOD = (1UL << 61) - 1;
    enum ulong POSITIVIZER = MOD * ((1UL << 3) - 1);
    uint base;
    ulong[] basePow = new ulong[](MAX_LENGTH + 1);
    ulong[] hash;

    this(string s) {
        auto rnd = Random(unpredictableSeed);
        base = uniform(129, int.max, rnd).to!uint;
        basePow[0] = 1;
        foreach (i ; 1 .. MAX_LENGTH + 1) {
            basePow[i] = calcMod(mul(basePow[i - 1], base));
        }

        hash = new ulong[](s.length + 1);
        foreach (i ; 0 .. s.length) {
            hash[i + 1] = calcMod(mul(hash[i], base) + s[i]);
        }
    }

    // hash(s[begin .. end])
    ulong slice(int begin, int end) {
        return calcMod(hash[end] + POSITIVIZER - mul(hash[begin], basePow[end - begin]));
    }

    ulong mul(ulong l, ulong r) {
        auto lu = l >> 31;
        auto ld = l & MASK31;
        auto ru = r >> 31;
        auto rd = r & MASK31;
        auto middleBit = ld * ru + lu * rd;
        return ((lu * ru) << 1) + ld * rd + ((middleBit & MASK30) << 31) + (middleBit >> 30);
    }

    ulong mul(ulong l, uint r) {
        auto lu = l >> 31;
        auto rd = r & MASK31;
        auto middleBit = lu * rd;
        return (l & MASK31) * rd + ((middleBit & MASK30) << 31) + (middleBit >> 30);
    }

    ulong calcMod(ulong val) {
        val = (val & MOD) + (val >> 61);
        if (val >= MOD) val -= MOD;
        return val;
    }
}






void scan(T...)(ref T args) {
    import std.stdio : readln;
    import std.algorithm : splitter;
    import std.conv : to;
    import std.range.primitives;

    auto line = readln().splitter();
    foreach (ref arg; args) {
        arg = line.front.to!(typeof(arg));
        line.popFront();
    }
    assert(line.empty);
}

void fillAll(R, T)(ref R arr, T value) {
    static if (is(typeof(arr[] = value))) {
        arr[] = value;
    }
    else {
        foreach (ref e; arr) {
            fillAll(e, value);
        }
    }
}

bool chmin(T, U...)(ref T x, U args) {
    bool isChanged;

    foreach (arg; args) {
        if (x > arg) {
            x = arg;
            isChanged = true;
        }
    }

    return isChanged;
}

bool chmax(T, U...)(ref T x, U args) {
    bool isChanged;

    foreach (arg; args) {
        if (x < arg) {
            x = arg;
            isChanged = true;
        }
    }

    return isChanged;
}
