import sys

input = lambda : sys.stdin.readline().rstrip()

sys.setrecursionlimit(max(1000, 10**9))

write = lambda x: sys.stdout.write(x+"\n")





n = int(eval(input()))

s = eval(input())

### ローリングハッシュ rolling hash

import random

# M = 10**9+7

# M = 1<<63 - 1

M = 92709568269121



b = random.choice(list(range(1,M)))

def rhash_list(s):

    l = [chr(v) for v in range(ord("a"), ord("z")+1)]

    d = {c:i+2 for i,c in enumerate(l)}

    ans = 0

    v = 1

    l = [0]

    for item in s:

        ans += d[item]*v

        v *= b

        ans %= M

        v %= M

        l.append(ans)

    return l

l = rhash_list(s)

if len(set(s))==n:

    ans = 0

else:

    binv = pow(b,M-2,M)

    pows = [None]*(n+1)

    v = 1

    for j in range(n+1):

        pows[j] = v

        v *= binv

        v %= M

#         pow(binv,j,M)

    ans = 0

    from collections import defaultdict

    for i in range(n//2, 0, -1):

        d = defaultdict(list)

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

            d[((l[j+i]-l[j])*pows[j])%M].append(j)

        for v in list(d.values()):

            if v[0]+i<=v[-1]:

                ans = i

        if ans>0:

            break

print(ans)
import sys

input = lambda : sys.stdin.readline().rstrip()

sys.setrecursionlimit(max(1000, 10**9))

write = lambda x: sys.stdout.write(x+"\n")





def z_algorithm(s):

    """

    各iについてs[0..n)とs[i..n)のLCP(Longest Common Prefix)の長さを求める

    s: str or (list of int )

    """

    n = len(s)

    if n==0:

        return []

    z = [None]*n

    z[0] = 0

    j = 0

    for i in range(1,n):

        k = 0 if j + z[j] <= i else min(j+z[j]-i, z[i-j])

        z[i] = k

        while i+k<n and s[k]==s[i+k]:

            k += 1

        z[i] = k

        if j+z[j] < i+z[i]:

            j = i

    z[0] = n

    return z

n = int(eval(input()))

s = eval(input())

ans = 0

for i in range(n):

    z = z_algorithm(s[i:])

    val = -1

    for j in range(len(z)):

        val = max(val, min(z[j], j))

    ans = max(ans, val)

#     print(z)

print(ans)
import sys

input = lambda: sys.stdin.readline().rstrip()
sys.setrecursionlimit(max(1000, 10**9))
write = lambda x: sys.stdout.write(x + "\n")
n = int(eval(input()))
s = eval(input())
### ローリングハッシュ rolling hash
import random

# M = 10**9+7
# M = 1<<63 - 1
M = 92709568269121
b = random.choice(list(range(1, M)))


def rhash_list(s):
    l = [chr(v) for v in range(ord("a"), ord("z") + 1)]
    d = {c: i + 2 for i, c in enumerate(l)}
    ans = 0
    v = 1
    l = [0]
    for item in s:
        ans += d[item] * v
        v *= b
        ans %= M
        v %= M
        l.append(ans)
    return l


l = rhash_list(s)
if len(set(s)) == n:
    ans = 0
else:
    binv = pow(b, M - 2, M)
    pows = [None] * (n + 1)
    v = 1
    for j in range(n + 1):
        pows[j] = v
        v *= binv
        v %= M
    #         pow(binv,j,M)
    ans = 0
    from collections import defaultdict

    for i in range(n // 2, 0, -1):
        d = defaultdict(list)
        for j in range(n - i + 1):
            d[((l[j + i] - l[j]) * pows[j]) % M].append(j)
        for v in list(d.values()):
            if v[0] + i <= v[-1]:
                ans = i
        if ans > 0:
            break
print(ans)

import sys

input = lambda: sys.stdin.readline().rstrip()
sys.setrecursionlimit(max(1000, 10**9))
write = lambda x: sys.stdout.write(x + "\n")


def z_algorithm(s):
    """
    各iについてs[0..n)とs[i..n)のLCP(Longest Common Prefix)の長さを求める
    s: str or (list of int )
    """
    n = len(s)
    if n == 0:
        return []
    z = [None] * n
    z[0] = 0
    j = 0
    for i in range(1, n):
        k = 0 if j + z[j] <= i else min(j + z[j] - i, z[i - j])
        z[i] = k
        while i + k < n and s[k] == s[i + k]:
            k += 1
        z[i] = k
        if j + z[j] < i + z[i]:
            j = i
    z[0] = n
    return z


n = int(eval(input()))
s = eval(input())
ans = 0
for i in range(n):
    z = z_algorithm(s[i:])
    val = -1
    for j in range(len(z)):
        val = max(val, min(z[j], j))
    ans = max(ans, val)
#     print(z)
print(ans)

+ + +def z_algorithm(s): +    """ +    各iについてs[0..n)とs[i..n)のLCP(Longest Common Prefix)の長さを求める +    s: str or (list of int ) +    """ +    n = len(s) +    if n == 0: +        return [] +    z = [None] * n +    z[0] = 0 +    j = 0 +    for i in range(1, n): +        k = 0 if j + z[j] <= i else min(j + z[j] - i, z[i - j]) +        z[i] = k +        while i + k < n and s[k] == s[i + k]: +            k += 1 +        z[i] = k +        if j + z[j] < i + z[i]: +            j = i +    z[0] = n +    return z + + -### ローリングハッシュ rolling hash -import random - -# M = 10**9+7 -# M = 1<<63 - 1 -M = 92709568269121 -b = random.choice(list(range(1, M))) - - -def rhash_list(s): -    l = [chr(v) for v in range(ord("a"), ord("z") + 1)] -    d = {c: i + 2 for i, c in enumerate(l)} -    ans = 0 -    v = 1 -    l = [0] -    for item in s: -        ans += d[item] * v -        v *= b -        ans %= M -        v %= M -        l.append(ans) -    return l - - -l = rhash_list(s) -if len(set(s)) == n: -    ans = 0 -else: -    binv = pow(b, M - 2, M) -    pows = [None] * (n + 1) -    v = 1 -    for j in range(n + 1): -        pows[j] = v -        v *= binv -        v %= M -    #         pow(binv,j,M) -    ans = 0 -    from collections import defaultdict - -    for i in range(n // 2, 0, -1): -        d = defaultdict(list) -        for j in range(n - i + 1): -            d[((l[j + i] - l[j]) * pows[j]) % M].append(j) -        for v in list(d.values()): -            if v[0] + i <= v[-1]: -                ans = i -        if ans > 0: -            break +ans = 0 +for i in range(n): +    z = z_algorithm(s[i:]) +    val = -1 +    for j in range(len(z)): +        val = max(val, min(z[j], j)) +    ans = max(ans, val) +#     print(z)