Buggy python submission (verdict: Time Limit Exceeded):
class ZAlgorithm(object):
    def __init__(self, s: str):
        self.lcp = self.__create_z(s)

    def __call__(self, i: int):
        return self.lcp[i]

    def __create_z(self, s: str):
        n = len(s)
        lcp = [n] + [0]*(n-1)
        l, r = 0, 0

        for t in range(1, n):
            if t>r:
                z = 0
                while t+z<n and s[0+z]==s[t+z]:
                    z += 1
                lcp[t] = z
                if z>0:
                    l, r = t, t+z-1
            else:
                p, b = t-l, r-t+1
                if lcp[p]<b:
                    lcp[t] = lcp[p]
                else:
                    i = r+1
                    while i<n and s[i]==s[i-t]:
                        i += 1
                    lcp[t] = i-t
                    l, r = t, i-1
        return lcp

def main():
    n, s = open(0).read().split()
    a = 0
    for i in range(int(n)-1):
        ss = s[i:]
        z_algo = ZAlgorithm(ss)
        for j in range(len(ss)):
            a = max(a, min(z_algo(j), j))
    print(a)

if __name__ == "__main__":
    main()


Fixed submission:
def f_e_dp():
    n = int(input())
    s = input()
    dp = [[0]*(n+1) for _ in range(n+1)]
    for i in reversed(range(n)):
        for j in reversed(range(n)):
            if s[i]==s[j] and i<j:
                dp[i][j] = dp[i+1][j+1]+1
    a = 0
    for i in range(n):
        for j in range(n):
            if i<j:
                a = max(a, min(j-i, dp[i][j]))
    print(a)

if __name__ == "__main__":
    f_e_dp()

Buggy python submission (verdict: Time Limit Exceeded):
class LcpArr(object):
    def __init__(self, orig_str: str):
        self.orig_str = orig_str
        self.sufs = self.__create_sufs()
        self.suf_arr, self.lcp_arr = self.__create_arr()

    def __call__(self, i: int, j: int):
        si, sj = sorted([self.suf_arr.index(i), self.suf_arr.index(j)])
        return min(self.lcp_arr[si:sj])

    def __create_sufs(self):
        n = len(self.orig_str)
        return [self.orig_str[i:] for i in range(n)] + [""]

    def __create_arr(self):
        n = len(self.orig_str)
        suf_arr = sorted(range(n), key=lambda x: self.sufs[x]) + [n]

        lcp_arr, c = [-1]*n, 0
        for i in range(n):
            si = suf_arr.index(i)
            lcp_arr[si] = c = self.__lcp_len(i, suf_arr[si+1], c)

        return suf_arr, lcp_arr

    def __lcp_len(self, i: int, j: int, c: int):
        suf, next_suf = self.sufs[i], self.sufs[j]

        l = c-1 if c>=2 else 0
        for i in range(l, min(len(suf), len(next_suf))):
            if suf[i] != next_suf[i]:
                break
            l += 1
        return l

def f_e():
    n = int(input())
    s = input()
    lcp = LcpArr(s)
    a = 0
    for i in range(n):
        for j in range(n):
            if i>=j:
                continue
            a = max(a, min(lcp(i, j), j-i))
    print(a)

if __name__ == "__main__":
    f_e()


Fixed submission:
def f_e_dp():
    n = int(input())
    s = input()
    dp = [[0]*(n+1) for _ in range(n+1)]
    for i in reversed(range(n)):
        for j in reversed(range(n)):
            if s[i]==s[j] and i<j:
                dp[i][j] = dp[i+1][j+1]+1
    a = 0
    for i in range(n):
        for j in range(n):
            if i<j:
                a = max(a, min(j-i, dp[i][j]))
    print(a)

if __name__ == "__main__":
    f_e_dp()

Buggy python submission (verdict: Time Limit Exceeded):
class LcpArr(object):
    def __init__(self, orig_str: str):
        self.orig_str = orig_str
        self.sufs = self.__create_sufs()
        self.suf_arr, self.lcp_arr = self.__create_arr()

    def __call__(self, i: int, j: int):
        si, sj = sorted([self.suf_arr.index(i), self.suf_arr.index(j)])
        return min(self.lcp_arr[si:sj])

    def __create_sufs(self):
        n = len(self.orig_str)
        return [self.orig_str[i:] for i in range(n)] + [""]

    def __create_arr(self):
        n = len(self.orig_str)
        suf_arr = sorted(range(n), key=lambda x: self.sufs[x]) + [n]

        lcp_arr = [-1]*n
        for i in range(n):
            si = suf_arr.index(i)
            lcp_arr[si] = self.__lcp_len(i, suf_arr[si+1])

        return suf_arr, lcp_arr

    def __lcp_len(self, i: int, j: int):
        suf, next_suf = self.sufs[i], self.sufs[j]

        l = 0
        for i in range(min(len(suf), len(next_suf))):
            if suf[i] != next_suf[i]:
                break
            l += 1
        return l

def f_e():
    n = int(input())
    s = input()
    lcp = LcpArr(s)
    a = 0
    for i in range(n):
        for j in range(n):
            if i>=j:
                continue
            a = max(a, min(lcp(i, j), j-i))
    print(a)

if __name__ == "__main__":
    f_e()


Fixed submission:
def f_e_dp():
    n = int(input())
    s = input()
    dp = [[0]*(n+1) for _ in range(n+1)]
    for i in reversed(range(n)):
        for j in reversed(range(n)):
            if s[i]==s[j] and i<j:
                dp[i][j] = dp[i+1][j+1]+1
    a = 0
    for i in range(n):
        for j in range(n):
            if i<j:
                a = max(a, min(j-i, dp[i][j]))
    print(a)

if __name__ == "__main__":
    f_e_dp()

Buggy python submission (verdict: Time Limit Exceeded):
def f_e():
    n = int(input())
    s = input()
    a = 0
    for si in range(n):
        s1, s2 = s[:si], s[si:]
        dp = [[0]*(len(s2)+1) for _ in range(len(s1)+1)]
        for i in range(len(s1)):
            for j in range(len(s2)):
                if s1[i]==s2[j]:
                    dp[i+1][j+1] = dp[i][j]+1
                else:
                    dp[i+1][j+1] = max(dp[i][j+1], dp[i+1][j])
        a = dp[-1][-1] if dp[-1][-1]>a else a
    print(a)

if __name__ == "__main__":
    f_e()


Fixed submission:
def f_e_dp():
    n = int(input())
    s = input()
    dp = [[0]*(n+1) for _ in range(n+1)]
    for i in reversed(range(n)):
        for j in reversed(range(n)):
            if s[i]==s[j] and i<j:
                dp[i][j] = dp[i+1][j+1]+1
    a = 0
    for i in range(n):
        for j in range(n):
            if i<j:
                a = max(a, min(j-i, dp[i][j]))
    print(a)

if __name__ == "__main__":
    f_e_dp()