#ifndef OUUAN
#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
#endif
#include<bits/stdc++.h>

#define int LoveLive
//#define FAST_IOSTREAM 1

#define For(i,l,r)for(int i=(l),i##end=(r);i<=i##end;++i)
#define FOR(i,r,l)for(int i=(r),i##end=(l);i>=i##end;--i)
#define SON(i,u)for(int i=head[u];i;i=nxt[i])
#define ms(a,x)memset(a,x,sizeof(a))
#define fi first
#define se second
#define pb emplace_back
#define pq priority_queue
#define isinf(x)(x>=INF?-1:x)
#define y1 why_is_there_a_function_called_y1
#define DEBUG(x)cerr<<(#x)<<":"<<x<<endl
using namespace std;
typedef long long LoveLive;typedef pair<int,int>pii;typedef vector<int>vi;
#ifdef int
const int INF=0x3f3f3f3f3f3f3f3fll;
#else
const int INF=0x3f3f3f3f;
#endif
const double eps=1e-9;mt19937 rng(chrono::steady_clock::now().time_since_epoch().
count());int randint(int l,int r){int out=rng()%(r-l+1)+l;return out>=l?out:out+
r-l+1;}
#ifdef FAST_IOSTREAM
#define br cout<<'\n'
#define sp cout<<' '
long long read(){long long x;cin>>x;return x;}template<typename T>void read(T&x){
cin>>x;}template<typename T>void write(const T&x){cout<<x;}
#else
#define br putchar('\n')
#define sp putchar(' ')
template<typename T>typename enable_if<!is_integral<T>::value,void>::type read(T
&x){cin>>x;}long long read(){char c;long long out=0,f=1;for(c=getchar();!isdigit
(c)&&c!='-';c=getchar());if(c=='-'){f=-1;c=getchar();}for(;isdigit(c);c=getchar())
out=(out<<3)+(out<<1)+c-'0';return out*f;}template<typename T>typename enable_if
<is_integral<T>::value,T>::type read(T&x){char c;T f=1;x=0;for(c=getchar();!isdigit
(c)&&c!='-';c=getchar());if(c=='-'){f=-1;c=getchar();}for(;isdigit(c);c=getchar())
x=(x<<3)+(x<<1)+c-'0';return x*=f;}char read(char&x){for(x=getchar();isspace(x);
x=getchar());return x;}double read(double&x){scanf("%lf",&x);return x;}template<
typename T>typename enable_if<!is_integral<T>::value,void>::type write(const T&x
){cout<<x;}template<typename T>typename enable_if<is_integral<T>::value,void>::type
write(const T&x){if(x<0){putchar('-');write(-x);return;}if(x>9)write(x/10);putchar
(x%10+'0');}void write(const char&x){putchar(x);}void write(const double&x){printf
("%.10lf",x);}
#endif
template<typename T,typename...Args>void read(T&x,Args&...args){read(x);read(args
...);}template<typename OutputIt,typename=typename enable_if<is_same<output_iterator_tag
,typename iterator_traits<OutputIt>::iterator_category>::value||(
is_base_of<forward_iterator_tag,typename iterator_traits<OutputIt>::iterator_category>::value
&&!is_const<OutputIt>::value)>::type>void read(OutputIt __first,OutputIt __last){for(;__first
!=__last;++__first)read(*__first);}template<typename InputIt,typename=typename enable_if
<is_base_of<input_iterator_tag,typename iterator_traits<InputIt>::iterator_category
>::value>::type>void wts(InputIt __first,InputIt __last){bool isFirst=true;for(;
__first!=__last;++__first){if(isFirst)isFirst=false;else sp;write(*__first);}br;}
template<typename InputIt,typename=typename enable_if<is_base_of<input_iterator_tag
,typename iterator_traits<InputIt>::iterator_category>::value>::type>void wtb(InputIt
__first,InputIt __last){for(;__first!=__last;++__first){write(*__first);br;}}template
<typename T>void wts(const T&x){write(x);sp;}template<typename T>void wtb(const
T&x){write(x);br;}template<typename T>void wte(const T&x){write(x);exit(0);}template
<typename T,typename...Args>void wts(const T&x,Args...args){wts(x);wts(args...);}
template<typename T,typename...Args>void wtb(const T&x,Args...args){wts(x);wtb(args
...);}template<typename T,typename...Args>void wte(const T&x,Args...args){wts(x);
wte(args...);}template<typename T>inline bool up(T&x,const T&y){return x<y?x=y,1
:0;}template<typename T>inline bool dn(T&x,const T&y){return y<x?x=y,1:0;}

const int N = 5010;
const int mod = 1000000007;

int n, p,tot,ans,lcs;
char s[N], t[N], str[N];

struct Node
{
	int len,par,ch[26];
} sam[N<<1];

void insert(int x)
{
	int np=++tot;
	sam[np].len=sam[p].len+1;
	while (~p&&sam[p].ch[x]==0)
	{
		sam[p].ch[x]=np;
		p=sam[p].par;
	}
	if (p==-1) sam[np].par=0;
	else
	{
		int q=sam[p].ch[x];
		if (sam[q].len==sam[p].len+1) sam[np].par=q;
		else
		{
			int nq=++tot;
			sam[nq].len=sam[p].len+1;
			memcpy(sam[nq].ch,sam[q].ch,sizeof(sam[q].ch));
			sam[nq].par=sam[q].par;
			sam[q].par=sam[np].par=nq;
			while (~p&&sam[p].ch[x]==q)
			{
				sam[p].ch[x]=nq;
				p=sam[p].par;
			}
		}
	}
	p=np;
}

signed main()
{
#ifdef FAST_IOSTREAM
	cin.sync_with_stdio(false);
	cin.tie(0);
#endif

	scanf("%d%s", &n, str);
	
	for (int mid = 1; mid < n - 1; ++mid)
	{
		for (int i = 0; i < mid; ++i) s[i] = str[i];
		s[mid] = 0;
		for (int i = 0; i < n - mid; ++i) t[i] = str[mid + i];
		t[n - mid] = 0;
		
		for (int i = 0; i < n * 2; ++i)
		{
			sam[i].len = sam[i].par = 0;
			ms(sam[i].ch, 0);
		}
		
		sam[0].par=-1;
		tot = p = 0;
		
		for (int i=0;s[i];++i) insert(s[i]-'a');
		
		p=lcs=0;
		for (int i=0;t[i];++i)
		{
			int x=t[i]-'a';
			while (p&&sam[p].ch[x]==0)
			{
				p=sam[p].par;
				lcs=sam[p].len;
			}
			if (sam[p].ch[x])
			{
				p=sam[p].ch[x];
				++lcs;
			}
			ans=max(ans,lcs);
		}
	}
	
	wtb(ans);
	
	return 0;
}

Measured memory_bytes: 2560