#include <bits/stdc++.h>
#include <boost/format.hpp>
#include <boost/integer/common_factor_rt.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/optional.hpp>

#ifdef DEBUG
#include "libs/debug.cpp"
#define DEBUG 1
#else
#define DEBUG 0
#endif

#define rep(i, n) repr((i), 0, (n))
#define repr(i, a, t) reps((i), (a), (t), 1)
#define reps(i, a, t, s) for (long long (i) = (a); (i) < (long long)(t); (i) += (s))
#define rrep(i, n) rrepr((i), (n) - 1, 0)
#define rrepr(i, a, t) rreps((i), (a), (t), 1)
#define rreps(i, a, t, s) for (long long (i) = (a); (i) >= (long long)(t); (i) -= (s))
#define each(v, c) for (auto &&(v) : (c))
#define all(c) (c).begin(), (c).end()

using namespace std;
namespace mp = boost::multiprecision;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using ml = mp::cpp_int;
template<typename T>
using optional = boost::optional<T>;
const auto none = boost::none;
const long long MOD = 1e9 + 7;
const long long INF = 1e18;

#include <bits/stdc++.h>
using namespace std;

/**
 * https://ja.wikipedia.org/wiki/クヌース–モリス–プラット法
 * 文字列検索
 */
class KMP {
 private:
  string needle;

 public:
  vector<long long> kmp;

  explicit KMP(const string &needle) : needle(needle), kmp(needle.size() + 2, 0) {
    // 部分マッチテーブルを構築
    kmp[0] = -1;
    kmp[1] = 0;
    {
      long long i = 2;
      long long j = 0;
      while (i < needle.size()) {
        if (needle[i - 1] == needle[j]) {
          kmp.at(i++) = ++j;
        } else if (j > 0) {
          j = kmp.at(j);
        } else {
          kmp.at(i++) = 0;
        }
      }
    }
  }

  /**
   * @param haystack
   * @param m The position of the current character in haystack
   * @param i The position of the current character in needle
   */
  long long index_of(const string &haystack, long long m = 0, long long i = 0) {
    while (m + i < haystack.size()) {
      if (needle.at(i) == haystack.at(m + i)) {
        if (++i == needle.size()) {
          return m;
        }
      } else {
        m += i - kmp.at(i);
        if (i > 0) {
          i = kmp.at(i);
        }
      }
    }
    return -1;
  }

  /**
   * ret[i]: haystack[i] 以降の文字列の最初が needle と同じなら true
   * @param haystack
   */
  vector<long long> search(const string &haystack) {
    vector<long long> ret(haystack.size(), false);

    long long m = 0;
    long long i = 0;
    while (m + i < haystack.size()) {
      m = index_of(haystack, m, i);
      if (m < 0) break;
      ret.at(m) = true;
      m += (long long) needle.size() - kmp.at(needle.size() - 1) - 1;
      i = max(0ll, kmp.at(needle.size() - 1));
    }
    return ret;
  }
};

int main() {
  cout << fixed << setprecision(10);
  cin.tie(nullptr);
  ios::sync_with_stdio(false);
  ifstream ifs;
  if (DEBUG) {
    ifs.open("src/_in.txt");
    cin.rdbuf(ifs.rdbuf());
  }

  ll N;
  cin >> N;
  string S;
  cin >> S;

//  auto kmp = KMP(S);
//  cout << kmp.kmp << "\n";

  ll ans = 0;
  repr (d, 1, N / 2 + 1) {
    ll cnt = 0;
    rep (i, N) {
      ll l = i;
      ll r = (i + d) % N;
      if (l > r) swap(l, r);
//      cout << l << ' ' << r << "\n";
      if (l == 0) cnt = 0;
      if (S[l] == S[r]) {
        ++cnt;
        ans = max(cnt, ans);
      } else {
        cnt = 0;
      }
      if (cnt >= d) {
        break;
      }
    }
  }
  cout << ans << "\n";
}

Measured memory_bytes: 384