#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using VI = vector<ll>;
using VV = vector<VI>;
using VS = vector<string>;

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; }

#define FOR(i,a,b) for(ll i=(a);i<(b);++i)
#define rep(i,b) FOR(i, 0, b)
#define ALL(v) (v).begin(), (v).end()
#define p(s) cout<<(s)<<endl
#define p2(s, t) cout << (s) << " " << (t) << endl
#define br() p("")
#define pn(s) cout << (#s) << " " << (s) << endl
#define p_yes() p("YES")
#define p_no() p("NO")
#define pb(s) push_back(s)
#define SZ(x) ((int)(x).size())

void no(){p_no(); exit(0);}
void yes(){p_yes(); exit(0);}

const ll mod = 1e9 + 7;
const ll inf = 1e18;

template< unsigned mod >
struct RollingHash {
  vector< unsigned > hashed, power;

  inline unsigned mul(unsigned a, unsigned b) const {
    unsigned long long x = (unsigned long long) a * b;
    unsigned xh = (unsigned) (x >> 32), xl = (unsigned) x, d, m;
    asm("divl %4; \n\t" : "=a" (d), "=d" (m) : "d" (xh), "a" (xl), "r" (mod));
    return m;
  }

  RollingHash(const string &s, unsigned base = 10007) {
    int sz = (int) s.size();
    hashed.assign(sz + 1, 0);
    power.assign(sz + 1, 0);
    power[0] = 1;
    for(int i = 0; i < sz; i++) {
      power[i + 1] = mul(power[i], base);
      hashed[i + 1] = mul(hashed[i], base) + s[i];
      if(hashed[i + 1] >= mod) hashed[i + 1] -= mod;
    }
  }

  unsigned get(int l, int r) const {
    unsigned ret = hashed[r] + mod - mul(hashed[l], power[r - l]);
    if(ret >= mod) ret -= mod;
    return ret;
  }

  unsigned connect(unsigned h1, int h2, int h2len) const {
    unsigned ret = mul(h1, power[h2len]) + h2;
    if(ret >= mod) ret -= mod;
    return ret;
  }

  int LCP(const RollingHash< mod > &b, int l1, int r1, int l2, int r2) {
    int len = min(r1 - l1, r2 - l2);
    int low = -1, high = len + 1;
    while(high - low > 1) {
      int mid = (low + high) / 2;
      if(get(l1, l1 + mid) == b.get(l2, l2 + mid)) low = mid;
      else high = mid;
    }
    return (low);
  }
};

using RH = RollingHash< 1000000007 >;
using RH2 = RollingHash< 1000000009 >;

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);

    // input
    ll N; cin >> N;
    string s; cin >> s;

    // 存在しない場合をチェック
    map<char, ll> mp;
    for(char c : s){
      mp[c]++;
    }
    if(mp.size()==N){
      p(0);
      return 0;
    }

    RH rh(s);
    RH rh2(s, 9973);

    ll left = 1; // can
    ll right = N/2+1; // can't

    ll ma = 0;
    while(left+1!=right){
      ll L = (left+right)/2; // この長さで見つけられるか
      bool found = false;
      
      map<pair<ll,ll>, ll> mp;
      for(int i=0; i<=N-L; i++){
        ll hash0 = rh.get(i, i+L);
        ll hash1 = rh2.get(i, i+L);
        auto pa = make_pair(hash0, hash1);
        if(mp.count(pa)>0){
          // hit?
          ll last_index = mp[pa];
          if(i-last_index>=L){
            found = true;
            chmax(ma, L);
            break;
          }
        }else{
          mp[pa] = i;
        }
      }
      if(found){
        left = L;
      }else{
        right = L;
      }
    }

    p(ma);
    return 0;
}



Measured memory_bytes: 640