

def resolve():

    N = int(eval(input()))

    S = eval(input())



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

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

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

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

                dp[i][j] = 0

            else:

                dp[i][j] = dp[i + 1][j + 1] + 1



    ans = 0

    for i in range(N):

        for j in range(N):

            now = min(dp[i][j], j - i)

            ans = max(ans, now)

    print(ans)





if __name__ == "__main__":

    resolve()



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



def resolve():

    N = int(eval(input()))

    S = eval(input())



    ans = 0

    for i in range(N):

        LCP = Z_algo(S[i:])

        for j, l in enumerate(LCP):

            tmp = min(l, j)

            ans = max(ans, tmp)

    print(ans)





if __name__ == "__main__":

    resolve()

def resolve():
    N = int(eval(input()))
    S = eval(input())
    dp = [[0] * (N + 1) for _ in range(N + 1)]
    for i in range(N - 1, -1, -1):
        for j in range(N - 1, -1, -1):
            if S[i] != S[j]:
                dp[i][j] = 0
            else:
                dp[i][j] = dp[i + 1][j + 1] + 1
    ans = 0
    for i in range(N):
        for j in range(N):
            now = min(dp[i][j], j - i)
            ans = max(ans, now)
    print(ans)


if __name__ == "__main__":
    resolve()

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


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


if __name__ == "__main__":
    resolve()

+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 + + -    dp = [[0] * (N + 1) for _ in range(N + 1)] -    for i in range(N - 1, -1, -1): -        for j in range(N - 1, -1, -1): -            if S[i] != S[j]: -                dp[i][j] = 0 -            else: -                dp[i][j] = dp[i + 1][j + 1] + 1 -        for j in range(N): -            now = min(dp[i][j], j - i) -            ans = max(ans, now) +        LCP = Z_algo(S[i:]) +        for j, l in enumerate(LCP): +            tmp = min(l, j) +            ans = max(ans, tmp)