# ABC141E - Who Says a Pun?

def main():

    N = int(eval(input()))

    S = input().rstrip()

    ok, ng = 0, N // 2 + 1

    while ng - ok > 1:

        mid = (ok + ng) // 2

        flg, checked = 0, set()

        for i in range(N - 2 * mid + 1):

            checked.add(S[i : i + mid])

            if S[i + mid : i + 2 * mid] in checked:

                flg = 1

                break

        if flg:

            ok = mid  # next mid will be longer

        else:

            ng = mid  # next mid will be shorter

    print(ok)  # max length of substrings appeared twice or more





if __name__ == "__main__":

    main()
# ABC141E - Who Says a Pun?

def resolve():

    N = int(eval(input()))

    S = input().rstrip()

    ok, ng = 0, N // 2 + 1

    while ng - ok > 1:

        mid = (ok + ng) // 2

        flg, checked = 0, set()

        for i in range(N - 2 * mid + 1):

            checked.add(hash(S[i : i + mid]))

            if hash(S[i + mid : i + 2 * mid]) in checked:

                flg = 1

                break

        if flg:

            ok = mid  # next mid will be longer

        else:

            ng = mid  # next mid will be shorter

    print(ok)  # max length of substrings appeared twice or more





resolve()
# ABC141E - Who Says a Pun?
def main():
    N = int(eval(input()))
    S = input().rstrip()
    ok, ng = 0, N // 2 + 1
    while ng - ok > 1:
        mid = (ok + ng) // 2
        flg, checked = 0, set()
        for i in range(N - 2 * mid + 1):
            checked.add(S[i : i + mid])
            if S[i + mid : i + 2 * mid] in checked:
                flg = 1
                break
        if flg:
            ok = mid  # next mid will be longer
        else:
            ng = mid  # next mid will be shorter
    print(ok)  # max length of substrings appeared twice or more


if __name__ == "__main__":
    main()

# ABC141E - Who Says a Pun?
def resolve():
    N = int(eval(input()))
    S = input().rstrip()
    ok, ng = 0, N // 2 + 1
    while ng - ok > 1:
        mid = (ok + ng) // 2
        flg, checked = 0, set()
        for i in range(N - 2 * mid + 1):
            checked.add(hash(S[i : i + mid]))
            if hash(S[i + mid : i + 2 * mid]) in checked:
                flg = 1
                break
        if flg:
            ok = mid  # next mid will be longer
        else:
            ng = mid  # next mid will be shorter
    print(ok)  # max length of substrings appeared twice or more


resolve()

-def main(): +def resolve(): -            checked.add(S[i : i + mid]) -            if S[i + mid : i + 2 * mid] in checked: +            checked.add(hash(S[i : i + mid])) +            if hash(S[i + mid : i + 2 * mid]) in checked: -if __name__ == "__main__": -    main() +resolve()