#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>

using namespace std;

const int MAX_N = int(1e6) + 10;
const long long int MOD=1e9+7;
const long long int INF=1e18;

typedef long long int ll;
/*
struct fenwick{
  int lim;
  long long int *tree;
  fenwick(int _lim){
      lim=_lim;
      tree=new long long int[lim];
  }
  void init(){
    for(int i=0;i<lim;i++){
      tree[i]=0;
    }
  }
  void update(int x,long long int v){
    while(x<lim){
      tree[x]+=v;
      x+=x&(-x);
    }
  }
  long long int query(int x){
    long long int ans=0;
    while(x>0){
      ans+=tree[x];
      x-=x&(-x);
    }
    return ans;
  }
  int _query(int k){
    int low=1;
    int high=500000;
    int ans=0;int x=k;
    while(low<=high){
      int mid=low+(high-low)/2;
      if(query(mid)>=x){
        ans=mid;
        high=mid-1;
      }else{
        low=mid+1;
      }
    }
    return ans;
  }
};
struct z_function{
  string &txt;
  int *z;
  z_function(string &_txt):txt(_txt){
    z=new int[1+txt.length()];
  }
  void cal(){
    z[0]=0;
    int l=0;
    int r=0;
    for(int i=1;i<txt.length();i++){
    //  cout<<l<<" "<<r<<endl;
      if(i>r){
        l=i;
        r=i;
        while(r<txt.length() && txt[r]==txt[r-l]){
          r++;
        }
      //  cout<<r<<" ";
        z[i]=r-l;
        r=r-1;
      }else{
              if(z[i-l]<r-i+1)
                z[i]=z[i-l];
              else{
                l=i;
                while(r<txt.length() && txt[r]==txt[r-l]){
                  r++;
                }
                z[i]=r-l;
                r=r-1;
              }
      }
    }
  }
};
struct palindromic_tree{
  map<char,struct palindromic_tree*>m;
  int length;
  int end_indx;
  struct palindromic_tree* suffix;
  palindromic_tree(int _length,int _end_indx){
    length=_length;
    end_indx=_end_indx;
  }
};
class palindromic_string{
public:
  string &s;
  struct palindromic_tree* real_root;
  struct palindromic_tree* imaginary_root;
  struct palindromic_tree* curr;
  long long int *prefix;
  palindromic_string(string &_s):s(_s){
       real_root=new palindromic_tree(0,-1);
       imaginary_root=new palindromic_tree(-1,-1);
       curr=real_root;
       real_root->suffix=imaginary_root;prefix=new long long int[1+s.length()];
       imaginary_root->suffix=imaginary_root;
  }
  void add(char ch){
    int indx=s.size();
    struct palindromic_tree* temp=curr;
    s+=ch;
    while(indx-temp->length-1<0 || s[indx-temp->length-1]!=s[indx])
      temp=temp->suffix;
    if((temp->m).find(ch)!=(temp->m).end()){
      curr=(temp->m)[ch];
      return;
    }else{
      curr=new palindromic_tree((temp->length)+2,indx);
    }

    (temp->m)[ch]=curr;

    if(curr->length==1){
      curr->suffix=real_root;
      return;
    }else{
      temp=temp->suffix;
      while(indx-temp->length-1<0 || s[indx-temp->length-1]!=s[indx])
        temp=temp->suffix;
      curr->suffix=(temp->m)[ch];
    }
  }

  void cal(){
    prefix[0]=0;
    long long int p=29LL;
    for(int i=0;i<s.length();i++){
      prefix[i+1]=(prefix[i]+(p*s[i]))%MOD;
      p=(p*p)%MOD;
    }
  }
};
struct prime_numbers{
  int *seive;
  int len;
  prime_numbers(int _len){
    len=_len;
    seive=new int[len+1];
  }
  void init(){
    seive[0]=1;
    seive[1]=1;
  }
  void cal(){
    for(int i=2;i*i<=len;i++){
      for(int j=i*i;j<=len;j+=i){
        seive[j]=1;
      }
    }
  }
};
*/
ll mul(ll a,ll b){
  ll ans=(a%MOD*b%MOD)%MOD;
  if(ans<0)ans+=MOD;
  return ans;
}
ll add(ll a,ll b){
  ll ans=(a+b)%MOD;
  if(ans>MOD)ans-=MOD;
  if(ans<0)ans+=MOD;
  return ans;
}
ll power(ll a,ll b,ll c){
  ll ans=1;
  while(b){
    if(b&1){
      ans=ans*a;
      ans=ans%c;
    }
    a=a*a;
    a=a%c;
    b=b/2;
  }
  return ans;
}

struct sparse{
  int table[200005][25];
  int n;
  sparse(int len1):n(len1){
  }
  void init(int *a){

    for(int i=1;i<=n;i++){
      table[i][0]=a[i];
    }

   // cout<<table[1][0]<<endl;

    for(int j=1;j<25;j++){
      for(int i=1;i<=n;i++){
        if(i+(1<<j)-1<=n){
          table[i][j]=__gcd(table[i][j-1],table[i+(1<<(j-1))][j-1]);
        }
      }
    }
  }
  int find(int *a,int start,int end){
    int dis=end-start+1;
    int g=0;
    for(int j=25;j>=0;j--){
      if(dis&(1<<j)){
     //     cout<<dis<<" "<<table[start][j]<<" "<<j<<endl;
          g=__gcd(g,table[start][j]);
          start=start+(1<<j);
      }
    }
    return g;
  }
};
inline ll gcd(ll a,ll b){
  while(b)a%=b,swap(a,b);
  return a;
}
string s2;int dp[5005][5005];
int lim,n;
int fun(int l1,int l2){
  if(l1>lim)return 0;
  if(l2>=n)return 0;
  if(dp[l1][l2]!=-1)return dp[l1][l2];
  if(s2[l1]!=s2[l2]){
    dp[l1][l2]=0;
    return 0;
  }
  return dp[l1][l2]=1+fun(l1+1,l2+1);
}
int main()
{
  //int n;
  cin>>n;
  //string s;
  cin>>s2;

  memset(dp,-1,sizeof(dp));
  int ans=0;
  for(int i=0;i<n;i++){
    for(int j=i+1;j<n;j++){
      lim=j-1;
      ans=max(ans,fun(i,j));
    }
  }

  

  

  cout<<ans<<endl;
}

Measured memory_bytes: 98176