import sys



def input():

    return sys.stdin.readline()[:-1]



from collections import defaultdict



N = int(eval(input()))

S = eval(input())



def is_pos(n,S,N):

    dd = defaultdict(int)

    flag =True

    for i in range(N-n+1):

        s = dd[S[i:i+n]]

        if s!=0:

            if i+1-s>=n:

                flag=False

                break

        else:

            dd[S[i:i+n]]=i+1

    return flag





def bisect(i,j,S,N):

    while j-i>1:

        if is_pos((i+j)//2,S,N):

            j = (i+j)//2

        else:

            i = (i+j)//2

    return i



print((bisect(0,N//2 + 1, S, N)))
class RollingHash():

    def __init__(self, s):

        self.length = len(s)

        self.base = 1009

        self.mod = (1 << 127) - 1

        self.hash = [0] * (self.length + 1)

        self.pow = [1] * (self.length + 1)

 

        for i in range(self.length):

            self.hash[i+1] = (self.hash[i] + ord(s[i])) * self.base % self.mod

            self.pow[i+1] = self.pow[i] * self.base % self.mod

 

    def get(self, l, r):

        t = self.hash[r] - self.hash[l] * self.pow[r-l] % self.mod

        t = (t + self.mod) % self.mod

        return t



N = int(eval(input()))

S = eval(input())



RH = RollingHash(S)



from collections import defaultdict



def check(length):

    if length==0:

        return True

    dd = defaultdict(int)

    flag = False

    for i in range(N-length+1):

        rh = RH.get(i,i+length)

        if dd[rh]==0:

            dd[rh] = i+1

        else:

            if dd[rh]+length<=i+1:

                flag=True

                break

    return flag



l = 0

r = N



while r-l>1:

    if check((l+r)//2):

        l = (l+r)//2

    else:

        r = (l+r)//2



print(l)
import sys


def input():
    return sys.stdin.readline()[:-1]


from collections import defaultdict

N = int(eval(input()))
S = eval(input())


def is_pos(n, S, N):
    dd = defaultdict(int)
    flag = True
    for i in range(N - n + 1):
        s = dd[S[i : i + n]]
        if s != 0:
            if i + 1 - s >= n:
                flag = False
                break
        else:
            dd[S[i : i + n]] = i + 1
    return flag


def bisect(i, j, S, N):
    while j - i > 1:
        if is_pos((i + j) // 2, S, N):
            j = (i + j) // 2
        else:
            i = (i + j) // 2
    return i


print((bisect(0, N // 2 + 1, S, N)))

class RollingHash:
    def __init__(self, s):
        self.length = len(s)
        self.base = 1009
        self.mod = (1 << 127) - 1
        self.hash = [0] * (self.length + 1)
        self.pow = [1] * (self.length + 1)
        for i in range(self.length):
            self.hash[i + 1] = (self.hash[i] + ord(s[i])) * self.base % self.mod
            self.pow[i + 1] = self.pow[i] * self.base % self.mod

    def get(self, l, r):
        t = self.hash[r] - self.hash[l] * self.pow[r - l] % self.mod
        t = (t + self.mod) % self.mod
        return t


N = int(eval(input()))
S = eval(input())
RH = RollingHash(S)
from collections import defaultdict


def check(length):
    if length == 0:
        return True
    dd = defaultdict(int)
    flag = False
    for i in range(N - length + 1):
        rh = RH.get(i, i + length)
        if dd[rh] == 0:
            dd[rh] = i + 1
        else:
            if dd[rh] + length <= i + 1:
                flag = True
                break
    return flag


l = 0
r = N
while r - l > 1:
    if check((l + r) // 2):
        l = (l + r) // 2
    else:
        r = (l + r) // 2
print(l)

-import sys +class RollingHash: +    def __init__(self, s): +        self.length = len(s) +        self.base = 1009 +        self.mod = (1 << 127) - 1 +        self.hash = [0] * (self.length + 1) +        self.pow = [1] * (self.length + 1) +        for i in range(self.length): +            self.hash[i + 1] = (self.hash[i] + ord(s[i])) * self.base % self.mod +            self.pow[i + 1] = self.pow[i] * self.base % self.mod +    def get(self, l, r): +        t = self.hash[r] - self.hash[l] * self.pow[r - l] % self.mod +        t = (t + self.mod) % self.mod +        return t -def input(): -    return sys.stdin.readline()[:-1] - - -from collections import defaultdict +RH = RollingHash(S) +from collections import defaultdict -def is_pos(n, S, N): +def check(length): +    if length == 0: +        return True -    flag = True -    for i in range(N - n + 1): -        s = dd[S[i : i + n]] -        if s != 0: -            if i + 1 - s >= n: -                flag = False +    flag = False +    for i in range(N - length + 1): +        rh = RH.get(i, i + length) +        if dd[rh] == 0: +            dd[rh] = i + 1 +        else: +            if dd[rh] + length <= i + 1: +                flag = True -        else: -            dd[S[i : i + n]] = i + 1 -def bisect(i, j, S, N): -    while j - i > 1: -        if is_pos((i + j) // 2, S, N): -            j = (i + j) // 2 -        else: -            i = (i + j) // 2 -    return i - - -print((bisect(0, N // 2 + 1, S, N))) +l = 0 +r = N +while r - l > 1: +    if check((l + r) // 2): +        l = (l + r) // 2 +    else: +        r = (l + r) // 2 +print(l)