import sys
def input(): return sys.stdin.readline().rstrip()


def is_ok(arg, S):
    # 条件を満たすかどうか？問題ごとに定義
    dic = {}
    ans = False
    for i in range(len(S)-arg+1):
        c = S[i:i+arg]
        if c in dic:
            if i-dic[c] >= arg:
                ans = True
                break
        else:
            dic[c] = i
    return ans


def meguru_bisect(ng, ok, S):
    '''
    初期値のng,okを受け取り,is_okを満たす最小(最大)のokを返す
    まずis_okを定義すべし
    ng ok は  とり得る最小の値-1 とり得る最大の値+1
    最大最小が逆の場合はよしなにひっくり返す
    '''
    while (abs(ok - ng) > 1):
        mid = (ok + ng) // 2
        if is_ok(mid, S):
            ok = mid
        else:
            ng = mid
    return ok


def main():
    N = int(input())
    S = input()
    print(meguru_bisect((N//2)+1, -1, S))


if __name__ == '__main__':
    main() import sys sys def input(): return sys.stdin.readline().rstrip() input def is_ok(arg, S):
    # 条件を満たすかどうか？問題ごとに定義
    dic = {}
    ans = False
    for i in range(len(S)-arg+1):
        c = S[i:i+arg]
        if c in dic:
            if i-dic[c] >= arg:
                ans = True
                break
        else:
            dic[c] = i
    return ans is_ok dic = {} dic {} ans = False ans False for i in range(len(S)-arg+1):
        c = S[i:i+arg]
        if c in dic:
            if i-dic[c] >= arg:
                ans = True
                break
        else:
            dic[c] = i
     i range(len(S)-arg+1) range len(S)-arg+1 len(S)-arg len(S) len S arg 1 c = S[i:i+arg] c S[i:i+arg] S i:i+arg i i+arg i arg if c in dic:
            if i-dic[c] >= arg:
                ans = True
                break
        else:
            dic[c] = i
     c in dic c dic if i-dic[c] >= arg:
                ans = True
                break
         i-dic[c] >= arg i-dic[c] i dic[c] dic c arg ans = True ans True break dic[c] = i dic[c] dic c i return ans ans arg arg S S def meguru_bisect(ng, ok, S):
    '''
    初期値のng,okを受け取り,is_okを満たす最小(最大)のokを返す
    まずis_okを定義すべし
    ng ok は  とり得る最小の値-1 とり得る最大の値+1
    最大最小が逆の場合はよしなにひっくり返す
    '''
    while (abs(ok - ng) > 1):
        mid = (ok + ng) // 2
        if is_ok(mid, S):
            ok = mid
        else:
            ng = mid
    return ok meguru_bisect '''
    初期値のng,okを受け取り,is_okを満たす最小(最大)のokを返す
    まずis_okを定義すべし
    ng ok は  とり得る最小の値-1 とり得る最大の値+1
    最大最小が逆の場合はよしなにひっくり返す
    ''' while (abs(ok - ng) > 1):
        mid = (ok + ng) // 2
        if is_ok(mid, S):
            ok = mid
        else:
            ng = mid
     abs(ok - ng) > 1 abs(ok - ng) abs ok - ng ok ng 1 mid = (ok + ng) // 2 mid (ok + ng) // 2 ok + ng ok ng 2 if is_ok(mid, S):
            ok = mid
        else:
            ng = mid
     is_ok(mid, S) is_ok mid S ok = mid ok mid ng = mid ng mid return ok ok ng ng ok ok S S def main():
    N = int(input())
    S = input()
    print(meguru_bisect((N//2)+1, -1, S)) main N = int(input()) N int(input()) int input() input S = input() S input() input print(meguru_bisect((N//2)+1, -1, S)) print meguru_bisect((N//2)+1, -1, S) meguru_bisect (N//2)+1 N//2 N 2 1 -1 S if __name__ == '__main__':
    main() __name__ == '__main__' __name__ '__main__' main() main def is_ok(arg, S):
    # 条件を満たすかどうか？問題ごとに定義
    dic = {}
    ans = False
    for i in range(len(S)-arg+1):
        c = S[i:i+arg]
        if c in dic:
            if i-dic[c] >= arg:
                ans = True
                break
        else:
            dic[c] = i
    return ans def is_ok(arg, S):
    # 条件を満たすかどうか？問題ごとに定義
    dic = {}
    ans = False
    for i in range(len(S)-arg+1):
        c = S[i:i+arg]
        if c in dic:
            if i-dic[c] >= arg:
                ans = True
                break
        else:
            dic[c] = i
    return ans is_ok def input(): return sys.stdin.readline().rstrip() def input(): return sys.stdin.readline().rstrip() input def main():
    N = int(input())
    S = input()
    print(meguru_bisect((N//2)+1, -1, S)) def main():
    N = int(input())
    S = input()
    print(meguru_bisect((N//2)+1, -1, S)) main def meguru_bisect(ng, ok, S):
    '''
    初期値のng,okを受け取り,is_okを満たす最小(最大)のokを返す
    まずis_okを定義すべし
    ng ok は  とり得る最小の値-1 とり得る最大の値+1
    最大最小が逆の場合はよしなにひっくり返す
    '''
    while (abs(ok - ng) > 1):
        mid = (ok + ng) // 2
        if is_ok(mid, S):
            ok = mid
        else:
            ng = mid
    return ok def meguru_bisect(ng, ok, S):
    '''
    初期値のng,okを受け取り,is_okを満たす最小(最大)のokを返す
    まずis_okを定義すべし
    ng ok は  とり得る最小の値-1 とり得る最大の値+1
    最大最小が逆の場合はよしなにひっくり返す
    '''
    while (abs(ok - ng) > 1):
        mid = (ok + ng) // 2
        if is_ok(mid, S):
            ok = mid
        else:
            ng = mid
    return ok meguru_bisect
import sys
def input(): return sys.stdin.readline().rstrip()


def is_ok(arg, S):
    # 条件を満たすかどうか？問題ごとに定義
    dic = {}
    ans = False
    for i in range(len(S)-arg+1):
        c = S[i:i+arg]
        if c in dic:
            if i-dic[c] >= arg:
                ans = True
                break
        else:
            dic[c] = i
    return ans


def meguru_bisect(ng, ok, S):
    '''
    初期値のng,okを受け取り,is_okを満たす最小(最大)のokを返す
    まずis_okを定義すべし
    ng ok は  とり得る最小の値-1 とり得る最大の値+1
    最大最小が逆の場合はよしなにひっくり返す
    '''
    while (abs(ok - ng) > 1):
        mid = (ok + ng) // 2
        if is_ok(mid, S):
            ok = mid
        else:
            ng = mid
    return ok


def main():
    N = int(input())
    S = input()
    print(meguru_bisect((N//2)+1, -1, S))


if __name__ == '__main__':
    main()
