# -*- coding: utf-8 -*-
import sys
from collections import Counter, defaultdict
buff_readline = sys.stdin.buffer.readline
readline = sys.stdin.readline


class RollingHash():
    """
    Original code is https://tjkendev.github.io/procon-library/python/string/rolling_hash.html
    """
    class RH():
        def __init__(self, s, base, mod):
            self.base = base
            self.mod = mod
            self.rev = pow(base, mod-2, mod)

            l = len(s)
            self.h = h = [0]*(l+1)
            tmp = 0
            for i in range(l):
                num = ord(s[i])
                tmp = (tmp*base + num) % mod
                h[i+1] = tmp

            self.pw = pw = [1]*(len(s)+1)
            v = 1
            for i in range(l):
                pw[i+1] = v = v * base % mod

        def calc(self, l, r):
            return (self.h[r] - self.h[l] * self.pw[r-l]) % self.mod

    @staticmethod
    def gen(a, b, num):
        result = set()
        while 1:
            import random
            import math
            random.seed()
            while 1:
                v = random.randint(a, b)//2*2+1
                if v not in result:
                    break
            for x in range(3, int(math.sqrt(v))+1, 2):
                if v % x == 0:
                    break
            else:
                result.add(v)
                if len(result) == num:
                    break
        return result

    def __init__(self, s, rand=False, num=5):
        if rand:
            bases = RollingHash.gen(2, 10**3, num)
        else:
            assert num <= 10
            bases = [641, 103, 661, 293, 547, 311, 29, 457, 613, 599][:num]

        MOD = 10**9+7
        self.rhs = [self.RH(s, b, MOD) for b in bases]

    def calc(self, l, r):
        return tuple(rh.calc(l, r) for rh in self.rhs)


class Bisect:
    def __init__(self, func):
        self.__func = func

    def bisect_left(self, x, lo, hi):
        while lo < hi:
            mid = (lo+hi)//2
            if self.__func(mid) < x:
                lo = mid+1
            else:
                hi = mid
        return lo

    def bisect_right(self, x, lo, hi):
        while lo < hi:
            mid = (lo+hi)//2
            if x < self.__func(mid):
                hi = mid
            else:
                lo = mid+1
        return lo


def slv(N, S):
    srh = RollingHash(S)

    def f(m):
        h2i = defaultdict(list)
        for i in range(N-m+1):
            h2i[srh.calc(i, i+m)].append(i)

        for l in h2i.values():
            n = l[-1] - l[0]
            if n >= m:
                return 0
        return 1

    return Bisect(f).bisect_right(0, 1, N//2+1) - 1


def main():
    N = int(input())
    S = input()
    print(slv(N, S))


if __name__ == '__main__':
    main() import sys sys from collections import Counter, defaultdict buff_readline = sys.stdin.buffer.readline buff_readline sys.stdin.buffer.readline sys.stdin.buffer sys.stdin sys stdin buffer readline readline = sys.stdin.readline readline sys.stdin.readline sys.stdin sys stdin readline class RollingHash():
    """
    Original code is https://tjkendev.github.io/procon-library/python/string/rolling_hash.html
    """
    class RH():
        def __init__(self, s, base, mod):
            self.base = base
            self.mod = mod
            self.rev = pow(base, mod-2, mod)

            l = len(s)
            self.h = h = [0]*(l+1)
            tmp = 0
            for i in range(l):
                num = ord(s[i])
                tmp = (tmp*base + num) % mod
                h[i+1] = tmp

            self.pw = pw = [1]*(len(s)+1)
            v = 1
            for i in range(l):
                pw[i+1] = v = v * base % mod

        def calc(self, l, r):
            return (self.h[r] - self.h[l] * self.pw[r-l]) % self.mod

    @staticmethod
    def gen(a, b, num):
        result = set()
        while 1:
            import random
            import math
            random.seed()
            while 1:
                v = random.randint(a, b)//2*2+1
                if v not in result:
                    break
            for x in range(3, int(math.sqrt(v))+1, 2):
                if v % x == 0:
                    break
            else:
                result.add(v)
                if len(result) == num:
                    break
        return result

    def __init__(self, s, rand=False, num=5):
        if rand:
            bases = RollingHash.gen(2, 10**3, num)
        else:
            assert num <= 10
            bases = [641, 103, 661, 293, 547, 311, 29, 457, 613, 599][:num]

        MOD = 10**9+7
        self.rhs = [self.RH(s, b, MOD) for b in bases]

    def calc(self, l, r):
        return tuple(rh.calc(l, r) for rh in self.rhs) RollingHash """
    Original code is https://tjkendev.github.io/procon-library/python/string/rolling_hash.html
    """ class RH():
        def __init__(self, s, base, mod):
            self.base = base
            self.mod = mod
            self.rev = pow(base, mod-2, mod)

            l = len(s)
            self.h = h = [0]*(l+1)
            tmp = 0
            for i in range(l):
                num = ord(s[i])
                tmp = (tmp*base + num) % mod
                h[i+1] = tmp

            self.pw = pw = [1]*(len(s)+1)
            v = 1
            for i in range(l):
                pw[i+1] = v = v * base % mod

        def calc(self, l, r):
            return (self.h[r] - self.h[l] * self.pw[r-l]) % self.mod

     RH def __init__(self, s, base, mod):
            self.base = base
            self.mod = mod
            self.rev = pow(base, mod-2, mod)

            l = len(s)
            self.h = h = [0]*(l+1)
            tmp = 0
            for i in range(l):
                num = ord(s[i])
                tmp = (tmp*base + num) % mod
                h[i+1] = tmp

            self.pw = pw = [1]*(len(s)+1)
            v = 1
            for i in range(l):
                pw[i+1] = v = v * base % mod

         __init__ self.base = base self.base self base base self.mod = mod self.mod self mod mod self.rev = pow(base, mod-2, mod) self.rev self rev pow(base, mod-2, mod) pow base mod-2 mod 2 mod l = len(s) l len(s) len s self.h = h = [0]*(l+1) self.h self h [0]*(l+1) [0] 0 l+1 l 1 = h = [0]*(l+1) h [0]*(l+1) tmp = 0 tmp 0 for i in range(l):
                num = ord(s[i])
                tmp = (tmp*base + num) % mod
                h[i+1] = tmp

             i range(l) range l num = ord(s[i]) num ord(s[i]) ord s[i] s i tmp = (tmp*base + num) % mod tmp (tmp*base + num) % mod tmp*base + num tmp*base tmp base num mod h[i+1] = tmp h[i+1] h i+1 i 1 tmp self.pw = pw = [1]*(len(s)+1) self.pw self pw [1]*(len(s)+1) [1] 1 len(s)+1 len(s) len s 1 = pw = [1]*(len(s)+1) pw [1]*(len(s)+1) v = 1 v 1 for i in range(l):
                pw[i+1] = v = v * base % mod

         i range(l) range l pw[i+1] = v = v * base % mod pw[i+1] pw i+1 i 1 v * base % mod v * base v base mod = v = v * base % mod v v * base % mod self self s s base base mod mod def calc(self, l, r):
            return (self.h[r] - self.h[l] * self.pw[r-l]) % self.mod

     calc return (self.h[r] - self.h[l] * self.pw[r-l]) % self.mod (self.h[r] - self.h[l] * self.pw[r-l]) % self.mod self.h[r] - self.h[l] * self.pw[r-l] self.h[r] self.h self h r self.h[l] * self.pw[r-l] self.h[l] self.h self h l self.pw[r-l] self.pw self pw r-l r l self.mod self mod self self l l r r def gen(a, b, num):
        result = set()
        while 1:
            import random
            import math
            random.seed()
            while 1:
                v = random.randint(a, b)//2*2+1
                if v not in result:
                    break
            for x in range(3, int(math.sqrt(v))+1, 2):
                if v % x == 0:
                    break
            else:
                result.add(v)
                if len(result) == num:
                    break
        return result

     gen result = set() result set() set while 1:
            import random
            import math
            random.seed()
            while 1:
                v = random.randint(a, b)//2*2+1
                if v not in result:
                    break
            for x in range(3, int(math.sqrt(v))+1, 2):
                if v % x == 0:
                    break
            else:
                result.add(v)
                if len(result) == num:
                    break
         1 import random random import math math random.seed() random.seed random seed while 1:
                v = random.randint(a, b)//2*2+1
                if v not in result:
                    break
             1 v = random.randint(a, b)//2*2+1 v random.randint(a, b)//2*2+1 random.randint(a, b)//2*2 random.randint(a, b)//2 random.randint(a, b) random.randint random randint a b 2 2 1 if v not in result:
                    break
             v not in result v result break for x in range(3, int(math.sqrt(v))+1, 2):
                if v % x == 0:
                    break
            else:
                result.add(v)
                if len(result) == num:
                    break
         x range(3, int(math.sqrt(v))+1, 2) range 3 int(math.sqrt(v))+1 int(math.sqrt(v)) int math.sqrt(v) math.sqrt math sqrt v 1 2 if v % x == 0:
                    break
             v % x == 0 v % x v x 0 break result.add(v) result.add result add v if len(result) == num:
                    break
         len(result) == num len(result) len result num break return result result a a b b num num @staticmethod
     gen staticmethod gen def __init__(self, s, rand=False, num=5):
        if rand:
            bases = RollingHash.gen(2, 10**3, num)
        else:
            assert num <= 10
            bases = [641, 103, 661, 293, 547, 311, 29, 457, 613, 599][:num]

        MOD = 10**9+7
        self.rhs = [self.RH(s, b, MOD) for b in bases]

     __init__ if rand:
            bases = RollingHash.gen(2, 10**3, num)
        else:
            assert num <= 10
            bases = [641, 103, 661, 293, 547, 311, 29, 457, 613, 599][:num]

         rand bases = RollingHash.gen(2, 10**3, num) bases RollingHash.gen(2, 10**3, num) RollingHash.gen RollingHash gen 2 10**3 10 3 num assert num <= 10 num <= 10 num 10 bases = [641, 103, 661, 293, 547, 311, 29, 457, 613, 599][:num] bases [641, 103, 661, 293, 547, 311, 29, 457, 613, 599][:num] [641, 103, 661, 293, 547, 311, 29, 457, 613, 599] 641 103 661 293 547 311 29 457 613 599 :num num MOD = 10**9+7 MOD 10**9+7 10**9 10 9 7 self.RH(s, b, MOD) for b in bases for b in bases b bases for b in bases self.RH(s, b, MOD) self.RH self RH s b MOD self.rhs = [self.RH(s, b, MOD) for b in bases] self.rhs self rhs [self.RH(s, b, MOD) for b in bases] self self s s rand=False rand False num=5 num 5 def calc(self, l, r):
        return tuple(rh.calc(l, r) for rh in self.rhs) calc return tuple(rh.calc(l, r) for rh in self.rhs) tuple(rh.calc(l, r) for rh in self.rhs) tuple rh.calc(l, r) rh.calc rh calc l r self self l l r r class Bisect:
    def __init__(self, func):
        self.__func = func

    def bisect_left(self, x, lo, hi):
        while lo < hi:
            mid = (lo+hi)//2
            if self.__func(mid) < x:
                lo = mid+1
            else:
                hi = mid
        return lo

    def bisect_right(self, x, lo, hi):
        while lo < hi:
            mid = (lo+hi)//2
            if x < self.__func(mid):
                hi = mid
            else:
                lo = mid+1
        return lo Bisect def __init__(self, func):
        self.__func = func

     __init__ self.__func = func self.__func self __func func self self func func def bisect_left(self, x, lo, hi):
        while lo < hi:
            mid = (lo+hi)//2
            if self.__func(mid) < x:
                lo = mid+1
            else:
                hi = mid
        return lo

     bisect_left while lo < hi:
            mid = (lo+hi)//2
            if self.__func(mid) < x:
                lo = mid+1
            else:
                hi = mid
         lo < hi lo hi mid = (lo+hi)//2 mid (lo+hi)//2 lo+hi lo hi 2 if self.__func(mid) < x:
                lo = mid+1
            else:
                hi = mid
         self.__func(mid) < x self.__func(mid) self.__func self __func mid x lo = mid+1 lo mid+1 mid 1 hi = mid hi mid return lo lo self self x x lo lo hi hi def bisect_right(self, x, lo, hi):
        while lo < hi:
            mid = (lo+hi)//2
            if x < self.__func(mid):
                hi = mid
            else:
                lo = mid+1
        return lo bisect_right while lo < hi:
            mid = (lo+hi)//2
            if x < self.__func(mid):
                hi = mid
            else:
                lo = mid+1
         lo < hi lo hi mid = (lo+hi)//2 mid (lo+hi)//2 lo+hi lo hi 2 if x < self.__func(mid):
                hi = mid
            else:
                lo = mid+1
         x < self.__func(mid) x self.__func(mid) self.__func self __func mid hi = mid hi mid lo = mid+1 lo mid+1 mid 1 return lo lo self self x x lo lo hi hi def slv(N, S):
    srh = RollingHash(S)

    def f(m):
        h2i = defaultdict(list)
        for i in range(N-m+1):
            h2i[srh.calc(i, i+m)].append(i)

        for l in h2i.values():
            n = l[-1] - l[0]
            if n >= m:
                return 0
        return 1

    return Bisect(f).bisect_right(0, 1, N//2+1) - 1 slv srh = RollingHash(S) srh RollingHash(S) RollingHash S def f(m):
        h2i = defaultdict(list)
        for i in range(N-m+1):
            h2i[srh.calc(i, i+m)].append(i)

        for l in h2i.values():
            n = l[-1] - l[0]
            if n >= m:
                return 0
        return 1

     f h2i = defaultdict(list) h2i defaultdict(list) defaultdict list for i in range(N-m+1):
            h2i[srh.calc(i, i+m)].append(i)

         i range(N-m+1) range N-m+1 N-m N m 1 h2i[srh.calc(i, i+m)].append(i) [srh.calc(i, i+m)].append [srh.calc(i, i+m)] h2i srh.calc(i, i+m) srh.calc srh calc i i+m i m append i for l in h2i.values():
            n = l[-1] - l[0]
            if n >= m:
                return 0
         l h2i.values() h2i.values h2i values n = l[-1] - l[0] n l[-1] - l[0] l[-1] l -1 l[0] l 0 if n >= m:
                return 0
         n >= m n m return 0 0 return 1 1 m m return Bisect(f).bisect_right(0, 1, N//2+1) - 1 Bisect(f).bisect_right(0, 1, N//2+1) - 1 Bisect(f).bisect_right(0, 1, N//2+1) (f).bisect_right (f) Bisect f bisect_right 0 1 N//2+1 N//2 N 2 1 1 N N S S def main():
    N = int(input())
    S = input()
    print(slv(N, S)) main N = int(input()) N int(input()) int input() input S = input() S input() input print(slv(N, S)) print slv(N, S) slv N S if __name__ == '__main__':
    main() __name__ == '__main__' __name__ '__main__' main() main def slv(N, S):
    srh = RollingHash(S)

    def f(m):
        h2i = defaultdict(list)
        for i in range(N-m+1):
            h2i[srh.calc(i, i+m)].append(i)

        for l in h2i.values():
            n = l[-1] - l[0]
            if n >= m:
                return 0
        return 1

    return Bisect(f).bisect_right(0, 1, N//2+1) - 1 def slv(N, S):
    srh = RollingHash(S)

    def f(m):
        h2i = defaultdict(list)
        for i in range(N-m+1):
            h2i[srh.calc(i, i+m)].append(i)

        for l in h2i.values():
            n = l[-1] - l[0]
            if n >= m:
                return 0
        return 1

    return Bisect(f).bisect_right(0, 1, N//2+1) - 1 slv class Bisect:
    def __init__(self, func):
        self.__func = func

    def bisect_left(self, x, lo, hi):
        while lo < hi:
            mid = (lo+hi)//2
            if self.__func(mid) < x:
                lo = mid+1
            else:
                hi = mid
        return lo

    def bisect_right(self, x, lo, hi):
        while lo < hi:
            mid = (lo+hi)//2
            if x < self.__func(mid):
                hi = mid
            else:
                lo = mid+1
        return lo class Bisect:
    def __init__(self, func):
        self.__func = func

    def bisect_left(self, x, lo, hi):
        while lo < hi:
            mid = (lo+hi)//2
            if self.__func(mid) < x:
                lo = mid+1
            else:
                hi = mid
        return lo

    def bisect_right(self, x, lo, hi):
        while lo < hi:
            mid = (lo+hi)//2
            if x < self.__func(mid):
                hi = mid
            else:
                lo = mid+1
        return lo Bisect class RollingHash():
    """
    Original code is https://tjkendev.github.io/procon-library/python/string/rolling_hash.html
    """
    class RH():
        def __init__(self, s, base, mod):
            self.base = base
            self.mod = mod
            self.rev = pow(base, mod-2, mod)

            l = len(s)
            self.h = h = [0]*(l+1)
            tmp = 0
            for i in range(l):
                num = ord(s[i])
                tmp = (tmp*base + num) % mod
                h[i+1] = tmp

            self.pw = pw = [1]*(len(s)+1)
            v = 1
            for i in range(l):
                pw[i+1] = v = v * base % mod

        def calc(self, l, r):
            return (self.h[r] - self.h[l] * self.pw[r-l]) % self.mod

    @staticmethod
    def gen(a, b, num):
        result = set()
        while 1:
            import random
            import math
            random.seed()
            while 1:
                v = random.randint(a, b)//2*2+1
                if v not in result:
                    break
            for x in range(3, int(math.sqrt(v))+1, 2):
                if v % x == 0:
                    break
            else:
                result.add(v)
                if len(result) == num:
                    break
        return result

    def __init__(self, s, rand=False, num=5):
        if rand:
            bases = RollingHash.gen(2, 10**3, num)
        else:
            assert num <= 10
            bases = [641, 103, 661, 293, 547, 311, 29, 457, 613, 599][:num]

        MOD = 10**9+7
        self.rhs = [self.RH(s, b, MOD) for b in bases]

    def calc(self, l, r):
        return tuple(rh.calc(l, r) for rh in self.rhs) class RollingHash():
    """
    Original code is https://tjkendev.github.io/procon-library/python/string/rolling_hash.html
    """
    class RH():
        def __init__(self, s, base, mod):
            self.base = base
            self.mod = mod
            self.rev = pow(base, mod-2, mod)

            l = len(s)
            self.h = h = [0]*(l+1)
            tmp = 0
            for i in range(l):
                num = ord(s[i])
                tmp = (tmp*base + num) % mod
                h[i+1] = tmp

            self.pw = pw = [1]*(len(s)+1)
            v = 1
            for i in range(l):
                pw[i+1] = v = v * base % mod

        def calc(self, l, r):
            return (self.h[r] - self.h[l] * self.pw[r-l]) % self.mod

    @staticmethod
    def gen(a, b, num):
        result = set()
        while 1:
            import random
            import math
            random.seed()
            while 1:
                v = random.randint(a, b)//2*2+1
                if v not in result:
                    break
            for x in range(3, int(math.sqrt(v))+1, 2):
                if v % x == 0:
                    break
            else:
                result.add(v)
                if len(result) == num:
                    break
        return result

    def __init__(self, s, rand=False, num=5):
        if rand:
            bases = RollingHash.gen(2, 10**3, num)
        else:
            assert num <= 10
            bases = [641, 103, 661, 293, 547, 311, 29, 457, 613, 599][:num]

        MOD = 10**9+7
        self.rhs = [self.RH(s, b, MOD) for b in bases]

    def calc(self, l, r):
        return tuple(rh.calc(l, r) for rh in self.rhs) RollingHash readline = sys.stdin.readline sys.stdin.readline readline buff_readline = sys.stdin.buffer.readline sys.stdin.buffer.readline buff_readline def main():
    N = int(input())
    S = input()
    print(slv(N, S)) def main():
    N = int(input())
    S = input()
    print(slv(N, S)) main
# -*- coding: utf-8 -*-
import sys
from collections import Counter, defaultdict
buff_readline = sys.stdin.buffer.readline
readline = sys.stdin.readline


class RollingHash():
    """
    Original code is https://tjkendev.github.io/procon-library/python/string/rolling_hash.html
    """
    class RH():
        def __init__(self, s, base, mod):
            self.base = base
            self.mod = mod
            self.rev = pow(base, mod-2, mod)

            l = len(s)
            self.h = h = [0]*(l+1)
            tmp = 0
            for i in range(l):
                num = ord(s[i])
                tmp = (tmp*base + num) % mod
                h[i+1] = tmp

            self.pw = pw = [1]*(len(s)+1)
            v = 1
            for i in range(l):
                pw[i+1] = v = v * base % mod

        def calc(self, l, r):
            return (self.h[r] - self.h[l] * self.pw[r-l]) % self.mod

    @staticmethod
    def gen(a, b, num):
        result = set()
        while 1:
            import random
            import math
            random.seed()
            while 1:
                v = random.randint(a, b)//2*2+1
                if v not in result:
                    break
            for x in range(3, int(math.sqrt(v))+1, 2):
                if v % x == 0:
                    break
            else:
                result.add(v)
                if len(result) == num:
                    break
        return result

    def __init__(self, s, rand=False, num=5):
        if rand:
            bases = RollingHash.gen(2, 10**3, num)
        else:
            assert num <= 10
            bases = [641, 103, 661, 293, 547, 311, 29, 457, 613, 599][:num]

        MOD = 10**9+7
        self.rhs = [self.RH(s, b, MOD) for b in bases]

    def calc(self, l, r):
        return tuple(rh.calc(l, r) for rh in self.rhs)


class Bisect:
    def __init__(self, func):
        self.__func = func

    def bisect_left(self, x, lo, hi):
        while lo < hi:
            mid = (lo+hi)//2
            if self.__func(mid) < x:
                lo = mid+1
            else:
                hi = mid
        return lo

    def bisect_right(self, x, lo, hi):
        while lo < hi:
            mid = (lo+hi)//2
            if x < self.__func(mid):
                hi = mid
            else:
                lo = mid+1
        return lo


def slv(N, S):
    srh = RollingHash(S)

    def f(m):
        h2i = defaultdict(list)
        for i in range(N-m+1):
            h2i[srh.calc(i, i+m)].append(i)

        for l in h2i.values():
            n = l[-1] - l[0]
            if n >= m:
                return 0
        return 1

    return Bisect(f).bisect_right(0, 1, N//2+1) - 1


def main():
    N = int(input())
    S = input()
    print(slv(N, S))


if __name__ == '__main__':
    main()
