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

#define DEBUG

// 型名の省略
typedef unsigned int uint;
typedef long long lint;
typedef unsigned long long ulint;

const int MOD = 1000000007;
const double PI=acos(-1.0);

// cinとcoutの高速化
#define endl "\n"
struct cinacc{cinacc(){cin.tie(0);ios::sync_with_stdio(false);}}cinaccc;
struct coutacc{coutacc(){cout.setf(ios::fixed);cout.precision(12);}}coutaccc;

// 繰り返し
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define rep_(i,n) for(int i=0;i<(int)(n-1);i++)
#define rep__(i,n) for(int i=n-1;i>=0;i--)

// メモリ関連
#define SZ(x) ((int)(x).size())
#define m0(x) memset(x,0,sizeof(x))
#define m1(x) memset(x,63,sizeof(x))
#define fill(x,y) memset(x,y,sizeof(x))
#define MEMSET(v,h) memset((v),h,sizeof(h)

// 最大値と最小値を更新する
template<class T>bool chmax(T &a,const T &b){if(a<b){a=b;return 1;}return 0;}
template<class T>bool chmin(T &a,const T &b){if(b<a){a=b;return 1;}return 0;}

// 要素を見つける
template<class T>T findVector(vector<T>v,int n){auto it=find(v.begin(),v.end(),n);size_t i=distance(v.begin(),it);if(i==v.size())return -1;return i;}

// 素数判定
bool isPrime(int n){if(n<2)return false;else if(n==2)return true;else if(n%2==0)return false;double sqrtNum=sqrt(n);for(int i=3;i<=sqrtNum;i+=2)if(n%i==0)return false;return true;}

// 入力関係
template<class T>T scan(){T t;cin>>t;return t;}
template<class T>T*scanArray(size_t n){T*a=(T*)malloc(n*sizeof(T));rep(i,n)cin>>a[i];return a;}
template<class T>list<T>scanList(size_t n){list<T>l;rep(i,n)cin>>l[i];return l;}
template<class T>vector<T>scanVector(size_t n){vector<T>v(n);rep(i,n)cin>>v[i];return v;}
template<class T>set<T>scanSet(size_t n){set<T>s;T t;rep(i,n){cin>>t;s.insert(t);}return s;}
template<class T,class U>map<T,U>scanMap(size_t n){map<T,U>m;vector<T>v(n);rep(i,n)cin>>v[i];U u;rep(i,n){cin>>u;m[v[i]]=u;}return m;}
template<class T>stack<T>scanStack(size_t n){stack<T>s;T t;rep(i,n){cin>>t;s.push(t);}return s;}
template<class T>queue<T>scanQueue(size_t n){queue<T>q;T t;rep(i,n){cin>>t;q.push(t);}return q;}
template<class T>priority_queue<T>scanPriorityQueue(size_t n){priority_queue<T>q;T t;rep(i,n){cin>>t;q.push(t);}return q;}
template<class T>deque<T>scanDeque(size_t n){deque<T>d;T t;rep(i,n){cin>>t;d.push_back(t);}return d;}
template<class T,class U>unordered_map<T, U>scanUnorderedMap(size_t n){unordered_map<T,U>m;vector<T>v(n);rep(i,n)cin>>v[i];U u;rep(i,n){cin>>u;m[v[i]]=u;}return m;}

// ソート
template<class T>vector<T>sortVector(vector<T>v,bool b=true){if(b)sort(v.begin(),v.end());else sort(v.begin(),v.end(),greater<T>());return v;}

// Algorithm

// FFT with Cooley–Tukey O(N log N)
vector<complex<double>>fft(vector<complex<double>>a,bool inverse=false){int n=a.size(),h=0;for(int i=0;1<<i<n;i++)h++;rep(i,n){int j=0;rep(k,h)j|=(i>>k&1)<<(h-1-k);if(i<j)swap(a[i],a[j]);}for(int b=1;b<n;b*=2){for(int j=0;j<b;j++){complex<double>w=polar(1.0,(2*M_PI)/(2*b)*j*(inverse?1:-1));for(int k=0;k<n;k+=b*2){complex<double>s=a[j+k];complex<double>t=a[j+k+b]*w;a[j+k]=s+t;a[j+k+b]=s-t;}}}if(inverse)rep(i,n)a[i]/=n;return a;}
// FFT with Cooley-Tucky O(N log N)
vector<complex<double>>fft(vector<double>a,bool inverse=false){vector<complex<double>>a_complex(a.size());rep(i,a.size())a_complex[i]=complex<double>(a[i],0);return fft(a_complex,inverse);}
// FFT による畳み込み O(N log N)
vector<double>convolve(vector<double>a,vector<double>b){int s=a.size()+b.size()-1,t=1;while(t<s)t*=2;a.resize(t);b.resize(t);vector<complex<double>>A=fft(a);vector<complex<double>>B=fft(b);rep(i,t)A[i]*=B[i];A=fft(A,true);a.resize(s);rep(i,s)a[i]=A[i].real();return a;}

// Z-Algorithm O(|S|)
vector<ulint>a(5000);
vector<ulint>z_algorithm(string s){/*vector<ulint>a(s.length());*/a[0]=s.size();for(ulint i=1,j=0,k;i<s.size();){while(i+j<s.size()&&s[j]==s[i+j])++j;a[i]=j;k=!!j;while(i+k<s.size()&&k+a[k]<j)a[i+k]=a[k],++k;i+=k+!j;j-=k;}return a;}

// デバッグ用
#ifdef DEBUG
#define eprintf(...) fprintf(stderr, __VA_ARGS__)
template<class T>void printArray(T*a,size_t n){cout<<"[DEBUG] <array>"<<endl;rep(i,n)cout<<a[i]<<endl;}
template<class T>void printList(list<T>l){cout<<"[DEBUG] <list>"<<endl;rep(i,l.size())cout<<"["<<i<<"] "<<*next(l.begin(),i)<<endl;}
template<class T>void printVector(vector<T>v){cout<<"[DEBUG] <vector>"<<endl;rep(i,v.size())cout<<"["<<i<<"] "<<v[i]<<endl;}
template<class T>void printSet(set<T>s){cout<<"[DEBUG] <set>"<<endl;rep(i,s.size())cout<<"["<<i<<"] "<<*next(s.begin(),i)<<endl;}
template<class T,class U>void printMap(map<T,U>m){int k=0;cout<<"[DEBUG] <map>"<<endl;for(auto it=m.begin();it!=m.end();++it)cout<<"["<<k++<<"] "<<it->first<<","<<it->second<<endl;}
template<class T>void printStack(stack<T>s){size_t si=s.size();vector<T>v(si);cout<<"[DEBUG] <stack>"<<endl;rep(i,si){v[i]=s.top();s.pop();}rep__(i,si){cout<<"["<<si-i-1<<"] "<<v[i]<<endl;}}
template<class T>void printQueue(queue<T>q){size_t si=q.size();cout<<"[DEBUG] <queue>"<<endl;rep(i,si){cout<<"["<<i<<"] "<<q.front()<<endl;q.pop();}}
template<class T>void printPriorityQueue(priority_queue<T>q){size_t si=q.size();cout<<"[DEBUG] <priority_queue>"<<endl;rep(i,si){cout<<"["<<i<<"] "<<q.top()<<endl;q.pop();}}
template<class T>void printDeque(deque<T>d){size_t si=d.size();cout<<"[DEBUG] <deque>"<<endl;rep(i,si)cout<<d[i]<<endl;}
template<class T,class U>void printUnorderedMap(unordered_map<T,U>m){int k=0;cout<<"[DEBUG] <map>"<<endl;for(auto it=m.begin();it!=m.end();++it)cout<<"["<<k++<<"] "<<it->first<<","<<it->second<<endl;}

#else
#define eprintf(...) 42
template<class T>void printArray(T*a,size_t n){}
template<class T>void printList(list<T>l){}
template<class T>void printVector(vector<T>v){}
template<class T>void printSet(set<T>s){}
template<class T,class U>void printMap(map<T,U>m){}
template<class T>void printStack(stack<T>s){}
template<class T>void printQueue(queue<T>q){}
template<class T>void printDeque(deque<T>d){}
template<class T,class U>void printUnorderedMap(unordered_map<T,U>m){}
#endif

int main(void) {
    int n = scan<int>();
    string s = scan<string>();
    int ans = 0;
    rep(i, n) {
        string tmp = "";
        for(int j = i; j < n; j++) {
            tmp += s[j];
        }
        z_algorithm(tmp);
        rep(j, n) {
            ans = max(ans, min((int)a[j], j));
        }
    }
    cout<<ans<<endl;
    return 0;
}


Measured memory_bytes: 384