We call a sequence of strings t1, ..., tk a journey of length k, if for each i > 1 ti is a substring of ti - 1 and length of ti is strictly less than length of ti - 1. For example, {ab, b} is a journey, but {ab, c} and {a, a} are not.

Define a journey on string s as journey t1, ..., tk, such that all its parts can be nested inside s in such a way that there exists a sequence of strings u1, ..., uk + 1 (each of these strings can be empty) and s = u1 t1 u2 t2... uk tk uk + 1. As an example, {ab, b} is a journey on string abb, but not on bab because the journey strings ti should appear from the left to the right.

The length of a journey on a string is the number of strings in it. Determine the maximum possible length of a journey on the given string s.

Input

The first line contains a single integer n (1 ≤ n ≤ 500 000) — the length of string s.

The second line contains the string s itself, consisting of n lowercase Latin letters.

Output

Print one number — the maximum possible length of string journey on s.

Examples

Input

7
abcdbcc


Output

3


Input

4
bbcb


Output

2

Note

In the first sample, the string journey of maximum length is {abcd, bc, c}.

In the second sample, one of the suitable journeys is {bb, b}.
#include <bits/stdc++.h>
using namespace std;
template <typename Arg1>
void __f(const char* name, Arg1&& arg1) {
  cerr << name << " : " << arg1 << std::endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args) {
  const char* comma = strchr(names + 1, ',');
  cerr.write(names, comma - names) << " : " << arg1 << " | ";
  __f(comma + 1, args...);
}
const int N = 5e5 + 10;
int str[N];
int _rank[N], pos[N];
int CNT[N], _next[N];
bool bh[N], b2h[N];
bool smaller_first_char(int a, int b) { return str[a] < str[b]; }
void suffixSort(int n) {
  for (int i = 0; i < n; ++i) {
    pos[i] = i;
  }
  sort(pos, pos + n, smaller_first_char);
  for (int i = 0; i < n; ++i) {
    bh[i] = i == 0 || str[pos[i]] != str[pos[i - 1]];
    b2h[i] = false;
  }
  for (int h = 1; h < n; h <<= 1) {
    int buckets = 0;
    for (int i = 0, j; i < n; i = j) {
      j = i + 1;
      while (j < n && !bh[j]) j++;
      _next[i] = j;
      buckets++;
    }
    if (buckets == n) break;
    for (int i = 0; i < n; i = _next[i]) {
      CNT[i] = 0;
      for (int j = i; j < _next[i]; ++j) {
        _rank[pos[j]] = i;
      }
    }
    CNT[_rank[n - h]]++;
    b2h[_rank[n - h]] = true;
    for (int i = 0; i < n; i = _next[i]) {
      for (int j = i; j < _next[i]; ++j) {
        int s = pos[j] - h;
        if (s >= 0) {
          int head = _rank[s];
          _rank[s] = head + CNT[head]++;
          b2h[_rank[s]] = true;
        }
      }
      for (int j = i; j < _next[i]; ++j) {
        int s = pos[j] - h;
        if (s >= 0 && b2h[_rank[s]]) {
          for (int k = _rank[s] + 1; !bh[k] && b2h[k]; k++) b2h[k] = false;
        }
      }
    }
    for (int i = 0; i < n; ++i) {
      pos[_rank[i]] = i;
      bh[i] |= b2h[i];
    }
  }
  for (int i = 0; i < n; ++i) {
    _rank[pos[i]] = i;
  }
}
int height[N];
void getHeight(int n) {
  for (int i = 0; i < n; ++i) _rank[pos[i]] = i;
  height[0] = 0;
  for (int i = 0, h = 0; i < n; ++i) {
    if (_rank[i] > 0) {
      int j = pos[_rank[i] - 1];
      while (i + h < n && j + h < n && str[i + h] == str[j + h]) h++;
      height[_rank[i]] = h;
      if (h > 0) h--;
    }
  }
  for (int i = 0; i < n - 1; i++) height[i] = height[i + 1];
  height[n - 1] = 0;
}
const int logN = 20;
int ceillog[N];
int RMQ[logN][N];
inline int lcp(int i, int j, int n) {
  if (i == j) return n - pos[i];
  j--;
  int k = ceillog[j - i + 2] - 1;
  return min(RMQ[k][i], RMQ[k][j - (1 << k) + 1]);
}
char s[N];
int dp[N];
const int MEM = 1e7;
int lft[MEM], rgt[MEM], val[MEM];
int root[N], cnt = 0;
struct segtree {
  int num;
  segtree() { num = 0; }
  void push(int x, int v, int pos1, int pos2, int s = 0, int e = N - 1) {
    val[pos1] = max(val[pos2], v);
    if (s == e) return;
    int mid = (s + e) / 2;
    if (x <= mid) {
      rgt[pos1] = rgt[pos2];
      lft[pos1] = ++cnt;
      pos2 = lft[pos2];
      pos1 = cnt;
      push(x, v, pos1, pos2, s, mid);
    } else {
      lft[pos1] = lft[pos2];
      rgt[pos1] = ++cnt;
      pos2 = rgt[pos2];
      pos1 = cnt;
      push(x, v, pos1, pos2, mid + 1, e);
    }
  }
  void insert(int i, int position) {
    ++num;
    root[num] = ++cnt;
    push(position, i + 1, root[num], root[num - 1]);
  }
  int get(int rt, int l, int r, int s = 0, int e = N - 1) {
    if (l > e || s > r) return 0;
    if (s >= l && e <= r) return val[rt];
    int mid = (s + e) >> 1;
    return max(get(lft[rt], l, r, s, mid), get(rgt[rt], l, r, mid + 1, e));
  }
} st;
int n;
bool chk(int mx, int l, int r, bool error = 0) {
  int len = r - l + 1;
  if (mx < 0) return 0;
  int L, R;
  int lo = _rank[l], hi = n - 1;
  while (lo < hi) {
    int mid = (lo + hi + 1) >> 1;
    if (lcp(_rank[l], mid, n) >= len) {
      lo = mid;
    } else
      hi = mid - 1;
  }
  R = lo;
  lo = 0, hi = _rank[l];
  while (lo < hi) {
    int mid = (lo + hi) >> 1;
    if (lcp(mid, _rank[l], n) >= len) {
      hi = mid;
    } else
      lo = mid + 1;
  }
  L = lo;
  int mxval = st.get(root[mx + 1], L, R) - 1;
  if (mxval < 0) return 0;
  return dp[mxval + len - 1] >= len;
}
int main() {
  ceillog[1] = 0;
  int k;
  for (k = 1; (1 << k) < N; k++)
    for (int i = (1 << (k - 1)) + 1; i <= (1 << k); i++) ceillog[i] = k;
  for (int i = (1 << k); i < N; i++) ceillog[i] = k + 1;
  scanf("%d", &n);
  scanf("%s", s);
  reverse(s, s + n);
  for (int i = 0; i < n; i++) str[i] = s[i] - 'a';
  suffixSort(n);
  getHeight(n);
  int ans = 0;
  for (int i = n - 1; i >= 0; i--) {
    RMQ[0][i] = height[i];
    for (int j = 1; i + (1 << j) <= n; j++)
      RMQ[j][i] = min(RMQ[j - 1][i], RMQ[j - 1][i + (1 << (j - 1))]);
  }
  int len = 1;
  for (int i = 0; i < n; i++) {
    int mx = i - 2 * len;
    while (len + 1 <= n &&
           (chk(mx, i - len, i - 1) || chk(mx, i - len + 1, i))) {
      len++;
      mx -= 2;
    }
    dp[i] = len;
    st.insert(i, _rank[i]);
    ans = max(ans, dp[i]);
    len = max(len - 1, 1);
  }
  printf("%d\n", ans);
}
