n=int(input())
ss=input()

# Z-algorithm
# 文字列が与えられた時、各 i について「S と S[i:|S|-1] の最長共通接頭辞の長さ」を記録した配列 A を O(|S|) で構築するアルゴリズムです。
#s='aaabaaaab'
def func(s):
  a=[0]*len(s)
  a[0]=len(s)
  i,j=1,0
  while i<len(s):
    while i+j<len(s) and s[j]==s[i+j]:
      j+=1
    a[i]=j
    if j==0:
      i+=1
      continue
    k=1
    while i+k<len(s) and k+a[k]<j:
      a[i+k]=a[k]
      k+=1
    i+=k
    j-=k
  return a
ans=0
for i in range(n):
  a=func(ss[i:])
  for j in range(len(a)):
    ans=max(ans,min(a[j],j))
print(ans) n=int(input()) n int(input()) int input() input ss=input() ss input() input def func(s):
  a=[0]*len(s)
  a[0]=len(s)
  i,j=1,0
  while i<len(s):
    while i+j<len(s) and s[j]==s[i+j]:
      j+=1
    a[i]=j
    if j==0:
      i+=1
      continue
    k=1
    while i+k<len(s) and k+a[k]<j:
      a[i+k]=a[k]
      k+=1
    i+=k
    j-=k
  return a func a=[0]*len(s) a [0]*len(s) [0] 0 len(s) len s a[0]=len(s) a[0] a 0 len(s) len s i,j=1,0 i 1 j 0 while i<len(s):
    while i+j<len(s) and s[j]==s[i+j]:
      j+=1
    a[i]=j
    if j==0:
      i+=1
      continue
    k=1
    while i+k<len(s) and k+a[k]<j:
      a[i+k]=a[k]
      k+=1
    i+=k
    j-=k
   i<len(s) i len(s) len s while i+j<len(s) and s[j]==s[i+j]:
      j+=1
     i+j<len(s) and s[j]==s[i+j] i+j<len(s) i+j i j len(s) len s s[j]==s[i+j] s[j] s j s[i+j] s i+j i j j+=1 j 1 a[i]=j a[i] a i j if j==0:
      i+=1
      continue
     j==0 j 0 i+=1 i 1 continue k=1 k 1 while i+k<len(s) and k+a[k]<j:
      a[i+k]=a[k]
      k+=1
     i+k<len(s) and k+a[k]<j i+k<len(s) i+k i k len(s) len s k+a[k]<j k+a[k] k a[k] a k j a[i+k]=a[k] a[i+k] a i+k i k a[k] a k k+=1 k 1 i+=k i k j-=k j k return a a s s ans=0 ans 0 for i in range(n):
  a=func(ss[i:])
  for j in range(len(a)):
    ans=max(ans,min(a[j],j)) i range(n) range n a=func(ss[i:]) a func(ss[i:]) func ss[i:] ss i: i for j in range(len(a)):
    ans=max(ans,min(a[j],j)) j range(len(a)) range len(a) len a ans=max(ans,min(a[j],j)) ans max(ans,min(a[j],j)) max ans min(a[j],j) min a[j] a j j print(ans) print ans a=func(ss[i:]) func(ss[i:]) a ans=0 0 ans n=int(input()) int(input()) n ans=max(ans,min(a[j],j)) max(ans,min(a[j],j)) ans ss=input() input() ss def func(s):
  a=[0]*len(s)
  a[0]=len(s)
  i,j=1,0
  while i<len(s):
    while i+j<len(s) and s[j]==s[i+j]:
      j+=1
    a[i]=j
    if j==0:
      i+=1
      continue
    k=1
    while i+k<len(s) and k+a[k]<j:
      a[i+k]=a[k]
      k+=1
    i+=k
    j-=k
  return a def func(s):
  a=[0]*len(s)
  a[0]=len(s)
  i,j=1,0
  while i<len(s):
    while i+j<len(s) and s[j]==s[i+j]:
      j+=1
    a[i]=j
    if j==0:
      i+=1
      continue
    k=1
    while i+k<len(s) and k+a[k]<j:
      a[i+k]=a[k]
      k+=1
    i+=k
    j-=k
  return a func
n=int(input())
ss=input()

# Z-algorithm
# 文字列が与えられた時、各 i について「S と S[i:|S|-1] の最長共通接頭辞の長さ」を記録した配列 A を O(|S|) で構築するアルゴリズムです。
#s='aaabaaaab'
def func(s):
  a=[0]*len(s)
  a[0]=len(s)
  i,j=1,0
  while i<len(s):
    while i+j<len(s) and s[j]==s[i+j]:
      j+=1
    a[i]=j
    if j==0:
      i+=1
      continue
    k=1
    while i+k<len(s) and k+a[k]<j:
      a[i+k]=a[k]
      k+=1
    i+=k
    j-=k
  return a
ans=0
for i in range(n):
  a=func(ss[i:])
  for j in range(len(a)):
    ans=max(ans,min(a[j],j))
print(ans)
