# -*- coding: utf-8 -*-

# ローリングハッシュ

from collections import defaultdict

N=eval(input())

s=input()



str="abcdefghijklmnopqrstuvwxyz"

D={}

for i,str in enumerate(str):

	D[str]=i+1



base=27

mod=10**9+7

hash=[]



for i,x in enumerate(s):

	if i==0: hash.append(D[x])

	else: hash.append( hash[-1]*base+D[x] )



def get(l,r):

	if l==0: return hash[r-1]

	else: return hash[r-1]-hash[l-1]*pow(base,(r-l))



# 長さmを固定し、区間 [i, i + m) のハッシュ値を求めて、長さmの共通文字列があるかを判定

def check(m):

	C={}

	for i in range(N):

		if i+m<=N:

			hash_value=get(i,i+m)

			if hash_value in C:

				if m<=i-C[hash_value]:

					return True

			else:

				C[hash_value]=i

	else:

		return False



l=0

h=N



while 1<(h-l):

	m=(l+h)/2

	if check(m):

		l=m

	else:

		h=m



print(l)

# -*- coding: utf-8 -*-

# RollingHash

from collections import defaultdict

N=eval(input())

s=input()



str="abcdefghijklmnopqrstuvwxyz"

D={}

for i,str in enumerate(str):

	D[str]=i+1



base=27

mod=10**9+7

hash=[]



for i,x in enumerate(s):

	if i==0: hash.append(D[x]%mod)

	else: hash.append( (hash[-1]*base+D[x])%mod )



def get(l,r):

	if l==0: return hash[r-1]%mod

	else: return ( hash[r-1]-hash[l-1]*pow(base,(r-l),mod) )%mod



# 長さmを固定し、区間 [i, i + m) のハッシュ値を求めて、長さmの共通文字列があるかを判定

def check(m):

	C={}

	for i in range(N):

		if i+m<=N:

			hash_value=get(i,i+m)

			if hash_value in C:

				if m<=i-C[hash_value]:

					return True

			else:

				C[hash_value]=i

	else:

		return False



l=0

h=N



while 1<(h-l):

	m=(l+h)/2

	if check(m):

		l=m

	else:

		h=m



print(l)

# -*- coding: utf-8 -*-
# ローリングハッシュ
from collections import defaultdict

N = eval(input())
s = input()
str = "abcdefghijklmnopqrstuvwxyz"
D = {}
for i, str in enumerate(str):
    D[str] = i + 1
base = 27
mod = 10**9 + 7
hash = []
for i, x in enumerate(s):
    if i == 0:
        hash.append(D[x])
    else:
        hash.append(hash[-1] * base + D[x])


def get(l, r):
    if l == 0:
        return hash[r - 1]
    else:
        return hash[r - 1] - hash[l - 1] * pow(base, (r - l))


# 長さmを固定し、区間 [i, i + m) のハッシュ値を求めて、長さmの共通文字列があるかを判定
def check(m):
    C = {}
    for i in range(N):
        if i + m <= N:
            hash_value = get(i, i + m)
            if hash_value in C:
                if m <= i - C[hash_value]:
                    return True
            else:
                C[hash_value] = i
    else:
        return False


l = 0
h = N
while 1 < (h - l):
    m = (l + h) / 2
    if check(m):
        l = m
    else:
        h = m
print(l)

# -*- coding: utf-8 -*-
# RollingHash
from collections import defaultdict

N = eval(input())
s = input()
str = "abcdefghijklmnopqrstuvwxyz"
D = {}
for i, str in enumerate(str):
    D[str] = i + 1
base = 27
mod = 10**9 + 7
hash = []
for i, x in enumerate(s):
    if i == 0:
        hash.append(D[x] % mod)
    else:
        hash.append((hash[-1] * base + D[x]) % mod)


def get(l, r):
    if l == 0:
        return hash[r - 1] % mod
    else:
        return (hash[r - 1] - hash[l - 1] * pow(base, (r - l), mod)) % mod


# 長さmを固定し、区間 [i, i + m) のハッシュ値を求めて、長さmの共通文字列があるかを判定
def check(m):
    C = {}
    for i in range(N):
        if i + m <= N:
            hash_value = get(i, i + m)
            if hash_value in C:
                if m <= i - C[hash_value]:
                    return True
            else:
                C[hash_value] = i
    else:
        return False


l = 0
h = N
while 1 < (h - l):
    m = (l + h) / 2
    if check(m):
        l = m
    else:
        h = m
print(l)

-# ローリングハッシュ +# RollingHash -        hash.append(D[x]) +        hash.append(D[x] % mod) -        hash.append(hash[-1] * base + D[x]) +        hash.append((hash[-1] * base + D[x]) % mod) -        return hash[r - 1] +        return hash[r - 1] % mod -        return hash[r - 1] - hash[l - 1] * pow(base, (r - l)) +        return (hash[r - 1] - hash[l - 1] * pow(base, (r - l), mod)) % mod