#define _CRT_SECURE_NO_WARNINGS
#define MOD 1000000007 
#define MOD2 998244353
#define INF 100000000
//#define MOD 922337203685419LL
#include <iostream>
#include <vector>
#include <list>
#include <set>
#include <bitset>
#include <map>
#include <stack>
#include <queue>
#include <deque>
#include <string>
#include <functional>
#include <algorithm>
#include <iterator>
#include <cstdio>
#include <utility>
#include <unordered_map>
#include <unordered_set>
#include <cmath>
#include <chrono>
#include <random>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;

typedef pair<int, int> pi;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<vector<int>> vvi;
typedef vector<vector<ll>> vvll;
#define FOR(i,a,b) for(ll i=(a);i<(b);++i)
#define RFOR(i,a,b) for(ll i=(a);i>(b);i--)
#define REP(i,n) FOR(i,0,n)
#define RREP(i,n) RFOR(i,n-1,-1)
#define ALL(obj) (obj).begin(), (obj).end()

inline ll madd(ll a, ll b) {
	a %= MOD;b %= MOD;
	return (a + b) % MOD;
}
inline ll msub(ll a, ll b) {
	a %= MOD;b %= MOD;
	a += MOD;
	return (a - b) % MOD;
}
inline ll mmul(ll a, ll b) {
	a %= MOD;b %= MOD;
	return (a*b) % MOD;
}
inline ll mpow(ll a, ll r) {
	long long res = 1;
	while (r > 0) {
		if (r & 1) res = res * a % MOD;
		a = a * a % MOD;
		r >>= 1;
	}
	return res;
}
inline ll minv(ll a) {
	a %= MOD;
	ll b = MOD, u = 0, v = 1;
	while (a) {
		ll t = b / a;
		b -= t * a; swap(a, b);
		u -= t * v; swap(u, v);
	}
	if (u < 0) u += MOD;
	return u;
}
inline ll mdiv(ll a, ll b) {
	a %= MOD;
	a *= minv(b);
	return a%MOD;
}


//ll fact[]
//inline ll combi(int a, int b) {
//	return mmul(fact[a], mmul(fact_inv[b], fact_inv[a - b]));
//}

struct UnionFind {
	vector<int> data;
	UnionFind(int size) : data(size, -1) { }
	bool unite(int x, int y) {
		x = root(x); y = root(y);
		if (x != y) {
			if (data[y] < data[x]) swap(x, y);
			data[x] += data[y]; data[y] = x;
		}
		return x != y;
	}
	bool same(int x, int y) {
		return root(x) == root(y);
	}
	int root(int x) {
		return data[x] < 0 ? x : data[x] = root(data[x]);
	}
	int size(int x) {
		return -data[root(x)];
	}
};

struct edge { ll to, cost; };


int main() {
	ll power[2501];
	power[0] = 1;
	REP(i, 2500) power[i + 1] = (power[i] * 29) % MOD;

	ll power2[2501];
	power2[0] = 1;
	REP(i, 2500) power2[i + 1] = (power2[i] * 29) % MOD2;

	int n;
	cin >> n;
	char s[5001];
	scanf("%s", s);

	vll hash_list;
	ll ha=0;
	hash_list.push_back(0);
	REP(i, n) {
		ha *= 29;
		ha += s[i] - 'a' + 2;
		ha %= MOD;
		hash_list.push_back(ha);
	}

	vll hash_list2;
	ll ha2 = 0;
	hash_list2.push_back(0);
	REP(i, n) {
		ha2 *= 29;
		ha2 += s[i] - 'a' + 2;
		ha2 %= MOD2;
		hash_list2.push_back(ha2);
	}

	RFOR(j, n/2, 0) {
		unordered_map<ll, int> ma;
		REP(i, n - j + 1) {
			ll x = (hash_list[i]*power[j])%MOD;
			x = (hash_list[i + j]+MOD-x)%MOD;
			if (ma.find(x) == ma.end()) ma[x] = i;
			else if (i >= ma[x] + j) {
				ll xx = (hash_list2[i]*power2[j])%MOD2;
				xx = (hash_list2[i + j]+MOD2-xx)%MOD2;
				ll xxx = (hash_list2[ma[x]]*power2[j])%MOD2;
				xxx = (hash_list2[ma[x] + j]+MOD2-xxx)%MOD2;
				if(xx==xxx){
					cout << j;
					return 0;
				}
			}
		}
	}

	cout << "0";
	return 0;
}


Measured memory_bytes: 736