#include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>
#include <numeric>
#include <functional>
#include <cmath>
#include <queue>
#include <stack>
#include <cstring>

using namespace std;

typedef long long LL;
typedef vector<LL> VL;
#define REPD(i,a,b) for (LL i=(a);i<(b);i++)
#define REP(i,n) REPD(i,0,n)

LL inputValue(){
  LL a;
  cin >> a;
  return a;
};

string inputString(){
  string a;
  cin >> a;
  return a;
};

vector<LL> inputVector(LL a){
  vector<LL> rv;
  REP(i, a){
    LL input;
    cin >> input;
    rv.push_back(input);
  }
  return rv;
}

vector<string> inputVectorString(LL a){
  vector<string> rv;
  REP(i, a){
    string input;
    cin >> input;
    rv.push_back(input);
  }
  return rv;
}
vector<vector<LL>> inputVector2D(LL a, LL b){
  vector<vector<LL>> rv;
  REP(i, a){
    rv.push_back(vector<LL>());
    REP(j, b) {
      LL input;
      cin >> input;
      rv.at(i).push_back(input);
    }
  }
  return rv;
}

#if 0
#define debug(d) debug1(__LINE__,#d, d)
void debug1(LL line, const char* name, vector<LL>& v) {
  cout << line << ":" << name << ":vector<LL>(" << v.size() << ") ";
  REP(i, (LL)v.size()) {
    cout << v.at(i) << " ";
  }
  cout << endl;
}
void debug1(LL line, const char* name, LL i) {
  cout << line << ":" << name << ":LL " << i << endl;;
}
void debug1(LL line, const char* name, vector<string>& v) {
  cout << line << ":" << name << ":vector<string>(" << v.size() << ") ";
  REP(i, (LL)v.size()) {
    cout << v.at(i) << " ";
  }
  cout << endl;
}
void debug1(LL line, const char* name, vector<vector<LL>>& v) {
  cout << line << ":" << name << ":vector<vector<LL>>(" << v.size() << ") ";
  REP(i, (LL)v.size()) {
    REP(j, (LL)v.at(i).size()) {
      cout << v.at(i).at(j) << " ";
    }
    cout << ", ";
  }
  cout << endl;
}
void debug1(LL line, const char* name, char* s) {
  cout << line << ":" << name << ":char* " << s << endl;;
}
void debug1(LL line, const char* name, vector<const char*>& v) {
  cout << line << ":" << name << ":vector<const char*>(" << v.size() << ") ";
  REP(i, (LL)v.size()) {
    cout << v.at(i) << " ";
  }
  cout << endl;
}
#else
#define debug(n)
#endif


bool cmp_strcmp(const char *a, const char *b) {
  return strcmp(a, b) > 0;
}

int main(int argc, const char * argv[]) {
	cout.precision(16);
  // source code

  auto n = inputValue();
  auto s = inputString();
  const char* p = s.c_str();
  vector<const char*> array;
  while (*p != '\0') {
    array.push_back(p);
    p++;
  }
  debug(array);
  sort(array.begin(), array.end(), &cmp_strcmp);
  debug(array);
  LL ret = 0;
  REP(i, array.size() -1) {
    auto check = [&](const char* p1, const char* p2) -> bool {
      LL max = p1 > p2 ? p1 - p2 : p2 - p1;
      debug(max);
      LL i=0;
      if (max < ret) return true;
      while(true) {
        if (i>=max) {
          debug(i);
          ret = ret<i?i:ret;
          return true;
        }
        if (p1[i] != p2[i]) {
          debug(i);
          ret = ret<i?i:ret;
          return false;
        }
        i++;
      }
    };
    LL d = 1;
    while(i+d < array.size()) {
      auto p1 = array.at(i);
      auto p2 = array.at(i+d);
      if(!check(p1, p2)) {
        break;
      }
      d++;
    }
  }
  cout << ret << endl;

  return 0;
}


Measured memory_bytes: 384