#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class MeetSemiLattice> struct SparseTable {
    vector<vector<MeetSemiLattice> > dat;
    vector<int> height;

    SparseTable() { }
    SparseTable(const vector<MeetSemiLattice> &vec) { init(vec); }
    void init(const vector<MeetSemiLattice> &vec) {
        int n = (int)vec.size(), h = 0;
        while ((1<<h) < n) ++h;
        dat.assign(h, vector<MeetSemiLattice>(1<<h));
        height.assign(n+1, 0);
        for (int i = 2; i <= n; i++) height[i] = height[i>>1]+1;
        for (int i = 0; i < n; ++i) dat[0][i] = vec[i];
        for (int i = 1; i < h; ++i)
            for (int j = 0; j < n; ++j)
                dat[i][j] = min(dat[i-1][j], dat[i-1][min(j+(1<<(i-1)),n-1)]);
    }

    MeetSemiLattice get(int a, int b) {
        return min(dat[height[b-a]][a], dat[height[b-a]][b-(1<<height[b-a])]);
    }
};

int n,k;
const int MAX_N = 10000;
int sa_rank[MAX_N + 1];
int sa_tmp[MAX_N + 1];

bool compare_sa(int i, int j){
  if(sa_rank[i]!=sa_rank[j])return sa_rank[i]<sa_rank[j];
  int ri = (i + k <= n) ? sa_rank[i + k] : -1;
  int rj = (j + k <= n) ? sa_rank[j + k] : -1;
  return ri < rj;
}

int sa[MAX_N + 1];
int lcp[MAX_N + 1];

// 接尾辞配列の構築
void build_sa(string s, int *sa) {
  n = s.length();
  for(int i = 0;i <= n; i++) {
    sa[i] = i;
    sa_rank[i] = (i < n) ? s[i] : -1;
  }
  for(k = 1; k <= n; k *= 2) {
    sort(sa, sa + n + 1, compare_sa);
    sa_tmp[sa[0]] = 0;
    for(int i=1;i<=n;i++){
      sa_tmp[sa[i]] = sa_tmp[sa[i-1]] + (compare_sa(sa[i-1], sa[i]) ? i : 0);
    }
    for(int i=0;i<=n;i++)sa_rank[i]=sa_tmp[i];
  }
}

// LCPの構築 sとsaを受け取る
void build_lcp(string s, int *sa, int *lcp) {
  int n = s.length();
  for(int i=0;i<=n;i++)sa_rank[sa[i]] = i;
  int h = 0;
  lcp[0]=0;
  for(int i=0;i<n;i++){
    int j = sa[sa_rank[i] - 1];
    if(h>0)h--;
    for(;j+h<n&&i+h<n;h++){
      if(s[j+h]!=s[i+h])break;
    }
    // cout<<h<<endl;
    lcp[sa_rank[i]-1]=h;
  }
}
SparseTable<int> st;

int main(int argc, char *argv[]) {
  ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);

  int N;
  string S;cin>>N>>S;
  build_sa(S, sa);
  build_lcp(S, sa, lcp);
  std::vector<int> lcp_vec;
  for(int i=0;i<=N;i++){
    lcp_vec.push_back(lcp[i]);
  }
  st.init(lcp_vec);

  // for(int i=0;i<N;i++){
  //   cout<<sa[i]<<":"<<S.substr(sa[i])<<endl;
  // }

  // for(int i=0;i<N;i++){
  //   if(lcp[i])cout<<lcp[i]<<endl;
  // }

  int res=0;
  for(int i=0;i<N;i++){
    // int a = sa[i];
    for(int j=i+1;j<N;j++){
      // int b = sa[j];
      int lcp = st.get(min(sa_rank[i], sa_rank[j]), max(sa_rank[i], sa_rank[j]));
      lcp = min(lcp, j-i);
      res = max(res, lcp);
                        // mn_lcp = min(mn_lcp, lcp[sa_rank[j-1]]);
      // res = max(res, min(mn_lcp, abs(a-b)));
    }
    // cout<<"a:"<<a<<", b:"<<b<<", lcp: "<<lcp[i]<<endl;
  }
  cout<<res<<endl;

  return 0;
}


// for(int i=0;i<N;i++){
//   int a = sa[i];
//   int b = sa[i+1];
//   // cout<<"a:"<<a<<", b:"<<b<<", lcp: "<<lcp[i]<<endl;
//   int mn = min(lcp[i], abs(a-b));
//   res = max(res, mn);
//   int mn_lcp = lcp[sa_rank[i]];
//   for(int j=i+2;j<=N;j++){
//     mn_lcp = min(mn_lcp, lcp[sa_rank[j-1]]);
//     b = sa[j];
//     res = max(res, min(mn_lcp, abs(a-b)));
//   }
// }


Measured memory_bytes: 896