#include <cassert>
#include <cstdio>
#include <cmath>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <sstream>
#include <vector>
#include <set>
#include <unordered_map>
#include <queue>
#include <numeric>
#include <algorithm>

using namespace std;
using lint = long long;
constexpr int MOD = 1000000007, INF = 1010101010;
constexpr lint LINF = 1LL << 60;

template <class T>
ostream &operator<<(ostream &os, const vector<T> &vec) {
	for (const auto &e : vec) os << e << (&e == &vec.back() ? "\n" : " ");
	return os;
}

#ifdef _DEBUG
template <class T>
void dump(const char* str, T &&h) { cerr << str << " = " << h << "\n"; };
template <class Head, class... Tail>
void dump(const char* str, Head &&h, Tail &&... t) {
	while (*str != ',') cerr << *str++; cerr << " = " << h << "\n";
	dump(str + (*(str + 1) == ' ' ? 2 : 1), t...);
}
#define DMP(...) dump(#__VA_ARGS__, __VA_ARGS__)
#else 
#define DMP(...) ((void)0)
#endif

template<class T>
inline bool chmax(T &a, T b) { return a < b && (a = b, true); }

#define SETNUM(rank, i,s) \
  NUM[i] = make_pair(make_pair(rank[i], i+s<n?rank[i+s]:n), i);
#define RENUMBER(rank) \
  sort(NUM, NUM+n); \
  rank[ NUM[0].second ] = 0; \
  for (int i = 1; i < n; ++i) \
    rank[ NUM[i].second ] = rank[ NUM[i-1].second ] \
      + (NUM[i-1].first != NUM[i].first) ;
vector<int> karp_miller_rosenberg(char *text, int r) {
  int n = strlen(text), k;
  int rank[n]; copy(text, text+n, rank);
  pair<pair<int,int>,int> NUM[n];
  for (k = 0; k*2 <= r; k ? k*=2 : ++k) { // power of 2
    for (int i = 0; i < n; ++i) SETNUM(rank, i, k);
    RENUMBER(rank);
  }
  for (int i = 0; i < n; ++i) SETNUM(rank, i, r-k);
  RENUMBER(rank);
  return vector<int>(rank, rank+n);
}

int ranks[32][200000];
void karp_miller_rosenberg_pre(char *text) {
  int n = strlen(text), m = 0;
  pair<pair<int,int>,int> NUM[n];
  copy(text, text+n, ranks[m]);
  for (int k = 0; k <= n; k ? k*=2 : ++k) { // power of 2
    for (int i = 0; i < n; ++i) SETNUM(ranks[m], i, k);
    if (k > 0) ++m; RENUMBER(ranks[m]);
  }
}
int repeated_factor(char *text, int r, int k) {
  int n = strlen(text), t, s;
  pair<pair<int,int>,int> NUM[n];
  int rank[n], count[n];
  for (s = 1, t = 0; s * 2 < r; s *= 2, ++t);
  for (int i = 0; i < n; ++i) SETNUM(ranks[t], i, r-s);
  RENUMBER(rank);
  memset(count, 0, sizeof(count));
  for (int i = 0; i < n; ++i)
    if (++count[ rank[i] ] >= k) return i;
  return -1;
}
string longest_repeated_factor(char *text, int k) {
  karp_miller_rosenberg_pre(text);
  int low = 1, high = strlen(text);
  while (low+1 < high) {
    int mid = (low + high) / 2;
    if (repeated_factor(text, mid, k) < 0) high = mid;
    else                                    low = mid;
  }
  int t = repeated_factor(text, low, k);
  return t >= 0 ? string(text+t, text+t+low+1) : "";
}

int main() {

	cin.tie(nullptr);
	ios::sync_with_stdio(false);

	int N;
	cin >> N;
	string s;
	cin >> s;

	auto check = [&](int len) {

		unordered_map<string, int> mp;
		for (int j = 0; j <= N - len; j++) {
			string tmp = s.substr(j, len);
			auto itr = mp.find(tmp);
			if (itr == mp.end()) mp.emplace(tmp, j);
			else if (j - itr->second >= len) return true;
		}
		
		return false;
	};

	vector<int> len(N/2 + 2);
	iota(len.begin(), len.end(), 0);
	cout << *partition_point(len.begin(), len.end(), check) - 1 << endl;

	return 0;
}


Measured memory_bytes: 6696