#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef vector<bool> vb;
typedef pair<int, int> ii;
typedef pair<int, bool> ib;

#define FOR(a, b, c) for(int a = b; a < c; ++a)
#define RFOR(a, b, c) for(int a = b; a >= c; --a)
#define mp(a, b) make_pair(a, b)
#define all(v) v.begin(), v.end()

#define ii pair<int, int>
#define vi vector<int>
#define vii vector<ii>
#define vvi vector<vi>
#define vb vector<bool>
#define fst first
#define snd second
#define MAXN 10010
#define LOGMAXN 20
#define MAXM 44100
#define LOGMAXN 20
#define INF 1000000007
#define INFLL 1000000000000000000LL
#define EPS 1e-9
#define MOD 1000000007LL


int n;
int a[MAXN];
int st1[MAXN][LOGMAXN];
int st2[MAXN][LOGMAXN];
int st3[MAXN][LOGMAXN];
 
void prep(int st[][LOGMAXN], int* a, bool mn)
{
    for(int i=n-1;i>=0;i--)
	{
        st[i][0]=a[i];
        for(int j=1;j<LOGMAXN;j++)
		if(mn)
            st[i][j]=min(st[i][j-1],st[min(i+(1<<(j-1)),n-1)][j-1]);       
		else
			st[i][j]=max(st[i][j-1],st[min(i+(1<<(j-1)),n-1)][j-1]);
    }
}
 
int query(int i, int j, int st[][LOGMAXN], bool mn)
{
    int m=j-i+1;
    if(m==1)return st[i][0];
    m=(31-__builtin_clz(m));
	if(mn)
		return min(st[i][m],st[j-(1<<m)+1][m]);
	else
		return max(st[i][m],st[j-(1<<m)+1][m]);
}


class SuffixArray {
	int RA[MAXN], tempRA[MAXN];
	int tempSA[MAXN], c[MAXN], n;
	int Phi[MAXN], PLCP[MAXN]; //para LCP
	void countingSort(int k, int SA[]) { // O(n)
		int i, sum, maxi = max(300, n);
		memset(c, 0, sizeof c);
		for (i = 0; i < n; i++) c[i + k < n ? RA[i + k] : 0]++;
		for (i = sum = 0; i < maxi; i++) {
			int t = c[i];
			c[i] = sum;
			sum += t;
		}
		for (i = 0; i < n; i++)
			tempSA[c[SA[i]+k < n ? RA[SA[i]+k] : 0]++] = SA[i];
		for (i = 0; i < n; i++) SA[i] = tempSA[i];
	}
public:
	void constructSA(char str[], int SA[]) { // O(nlogn)
		int i, k, r; n = strlen(str);
		str[n++] = '$'; str[n] = 0;
		for (i = 0; i < n; i++) RA[i] = str[i];
		for (i = 0; i < n; i++) SA[i] = i;
		for (k = 1; k < n; k <<= 1) {
			countingSort(k, SA);
			countingSort(0, SA);
			tempRA[SA[0]] = r = 0;
			for (i = 1; i < n; i++) 
				tempRA[SA[i]] = (RA[SA[i]] == RA[SA[i-1]] && RA[SA[i]+k] == RA[SA[i-1]+k]) ? r : ++r;
			for (i = 0; i < n; i++) RA[i] = tempRA[i];
			if (RA[SA[n-1]] == n-1) break;
		}
	}
	void computeLCP(char str[], int SA[], int LCP[]) { // O(n)
		int i, L; n = strlen(str);
		Phi[SA[0]] = -1;
		for (i = 1; i < n; i++)  Phi[SA[i]] = SA[i-1];
		for (i = L = 0; i < n; i++) {
			if (Phi[i] == -1) {
				PLCP[i] = 0; continue;
			}
			while (str[i + L] == str[Phi[i] + L]) L++;
			PLCP[i] = L;
			L = max(L-1, 0);
		}
		for (i = 0; i < n; i++) LCP[i] = PLCP[SA[i]];
	}
};

SuffixArray sa;

char str[MAXN];
int SA[MAXN], LCP[MAXN];

long long psum(int i) {
	if (i <= 0) return 0;
	return i*(i+1LL)/2;
}

int getValue(int i, int mid)
{
	int len = query(i+1, mid, st1, true);
	if(len == 0) return 0;
	int minI = query(i+1, mid, st2, true);
	int minLI = minI + len - 1;
	int maxI = query(i+1, mid, st3, false);
	int maxLI = maxI + len - 1;
	int curI = SA[i+1];
	int lastI = curI + len - 1;
	if(minLI < curI || maxI > lastI) return len;
	return -1;
}

int main()
{
	ios_base::sync_with_stdio(false); cin.tie(0);
	while(scanf("%d", &n) != EOF)
	{
		scanf(" %s", str);
		sa.constructSA(str, SA);
		sa.computeLCP(str, SA, LCP);
		for(int i = 1; i <= n; i++) 
		{
			a[i-1] = LCP[i];
		}
		prep(st1, a, true);
		for(int i = 1; i <= n; i++) 
		{
			a[i-1] = SA[i];
		}
		prep(st2, a, true);
		prep(st3, a, false);
		int ans = 0;
		FOR(i, 0, n-1)
		{
			int l = i+1;
			int h = n-1;
			while(h - l > 1)
			{
				int mid = (h + l)/2;
				if(getValue(i, mid) >= 0)
					h = mid;
				else
					l = mid+1;
			}
			int nval = getValue(i, l);
			if(nval < 0)
				nval = getValue(i, h);
			ans = max(ans, nval);
		}
		printf("%d\n", ans);
	}
	return 0;
}


Measured memory_bytes: 1664