import sys

input = sys.stdin.readline

N=int(eval(input()))

S=input().strip()

dp=[[0]*(N+1) for _ in range(N+1)]

for i in range(N-1,-1,-1):

    for j in range(N-1,i,-1):

        if S[i]==S[j]:

            dp[i][j]=max(dp[i][j],dp[i+1][j+1]+1)

#print(dp)

ans=0

for i in range(N):

    for j in range(N):

        ans=max(ans,min(dp[i][j],j-i))

print(ans)

import sys

input = sys.stdin.readline

N=int(eval(input()))

S=input().strip()

"""dp=[[0]*(N+1) for _ in range(N+1)]

for i in range(N-1,-1,-1):

    for j in range(N-1,i,-1):

        if S[i]==S[j]:

            dp[i][j]=max(dp[i][j],dp[i+1][j+1]+1)

#print(dp)

ans=0

for i in range(N):

    for j in range(N):

        ans=max(ans,min(dp[i][j],j-i))

print(ans)

"""



def Z_algo(S):

    n = len(S)

    LCP = [0]*n

    i = 1

    j = 0

    c = 0#最も末尾側までLCPを求めたインデックス

    for i in range(1, n):

        #i番目からのLCPが以前計算したcからのLCPに含まれている場合

        if i+LCP[i-c] < c+LCP[c]:

            LCP[i] = LCP[i-c]

        else:

            j = max(0, c+LCP[c]-i)

            while i+j < n and S[j] == S[i+j]: j+=1

            LCP[i] = j

            c = i

    LCP[0] = n

    return LCP



ans=0

for i in range(N):

    LCP=Z_algo(S[i:])

    #print(LCP)

    for j , l in enumerate(LCP):

        tmp=min(l,j)

        ans=max(ans,tmp)

print(ans)

import sys

input = sys.stdin.readline
N = int(eval(input()))
S = input().strip()
dp = [[0] * (N + 1) for _ in range(N + 1)]
for i in range(N - 1, -1, -1):
    for j in range(N - 1, i, -1):
        if S[i] == S[j]:
            dp[i][j] = max(dp[i][j], dp[i + 1][j + 1] + 1)
# print(dp)
ans = 0
for i in range(N):
    for j in range(N):
        ans = max(ans, min(dp[i][j], j - i))
print(ans)

import sys

input = sys.stdin.readline
N = int(eval(input()))
S = input().strip()
"""dp=[[0]*(N+1) for _ in range(N+1)]
for i in range(N-1,-1,-1):
    for j in range(N-1,i,-1):
        if S[i]==S[j]:
            dp[i][j]=max(dp[i][j],dp[i+1][j+1]+1)
#print(dp)
ans=0
for i in range(N):
    for j in range(N):
        ans=max(ans,min(dp[i][j],j-i))
print(ans)
"""


def Z_algo(S):
    n = len(S)
    LCP = [0] * n
    i = 1
    j = 0
    c = 0  # 最も末尾側までLCPを求めたインデックス
    for i in range(1, n):
        # i番目からのLCPが以前計算したcからのLCPに含まれている場合
        if i + LCP[i - c] < c + LCP[c]:
            LCP[i] = LCP[i - c]
        else:
            j = max(0, c + LCP[c] - i)
            while i + j < n and S[j] == S[i + j]:
                j += 1
            LCP[i] = j
            c = i
    LCP[0] = n
    return LCP


ans = 0
for i in range(N):
    LCP = Z_algo(S[i:])
    # print(LCP)
    for j, l in enumerate(LCP):
        tmp = min(l, j)
        ans = max(ans, tmp)
print(ans)

-dp = [[0] * (N + 1) for _ in range(N + 1)] -for i in range(N - 1, -1, -1): -    for j in range(N - 1, i, -1): -        if S[i] == S[j]: -            dp[i][j] = max(dp[i][j], dp[i + 1][j + 1] + 1) -# print(dp) +"""dp=[[0]*(N+1) for _ in range(N+1)] +for i in range(N-1,-1,-1): +    for j in range(N-1,i,-1): +        if S[i]==S[j]: +            dp[i][j]=max(dp[i][j],dp[i+1][j+1]+1) +#print(dp) +ans=0 +for i in range(N): +    for j in range(N): +        ans=max(ans,min(dp[i][j],j-i)) +print(ans) +""" + + +def Z_algo(S): +    n = len(S) +    LCP = [0] * n +    i = 1 +    j = 0 +    c = 0  # 最も末尾側までLCPを求めたインデックス +    for i in range(1, n): +        # i番目からのLCPが以前計算したcからのLCPに含まれている場合 +        if i + LCP[i - c] < c + LCP[c]: +            LCP[i] = LCP[i - c] +        else: +            j = max(0, c + LCP[c] - i) +            while i + j < n and S[j] == S[i + j]: +                j += 1 +            LCP[i] = j +            c = i +    LCP[0] = n +    return LCP + + -    for j in range(N): -        ans = max(ans, min(dp[i][j], j - i)) +    LCP = Z_algo(S[i:]) +    # print(LCP) +    for j, l in enumerate(LCP): +        tmp = min(l, j) +        ans = max(ans, tmp)