📜  门| GATE CS 2020 |问题 3(1)

📅  最后修改于: 2023-12-03 15:28:38.622000             🧑  作者: Mango

门 | GATE CS 2020 |问题 3

本文主要介绍 GATE CS 2020 中的问题 3,问题描述如下:

给定一个字符串 $S$ 和整数 $k$,找到长度为 $k$ 的子串中的最长重复子串,并返回该子串。

现在让我们来看一下实现这个问题的几种方法。

暴力搜索

最简单的方法是对所有长度为 $k$ 的子串进行比较。时间复杂度为 $O(n^2)$。

def longest_repeated_substring(S: str, k: int) -> str:
    n = len(S)
    max_len = 0
    max_str = ''
    for i in range(n - k + 1):
        for j in range(i + 1, n - k + 1):
            if S[i:i + k] == S[j:j + k] and k > max_len:
                max_len = k
                max_str = S[i:i + k]
    return max_str
后缀数组

后缀数组可以实现在 $O(n \log n)$ 的时间内解决该问题。

def longest_repeated_substring(S: str, k: int) -> str:
    n = len(S)
    suffixes = [(S[i:], i) for i in range(n - k + 1)]
    suffixes.sort()
    max_len = 0
    max_str = ''
    for i in range(n - k):
        if suffixes[i][1] < suffixes[i + 1][1] and len(set(suffixes[i][0][:k]).intersection(set(suffixes[i + 1][0][:k]))) > max_len:
            max_len = len(set(suffixes[i][0][:k]).intersection(set(suffixes[i + 1][0][:k])))
            max_str = suffixes[i][0][:k]
    return max_str
后缀树

后缀树可以实现在 $O(n)$ 的时间内解决该问题。

class Node:
    def __init__(self):
        self.children = {}
        self.idx_list = []
        
class SuffixTree:
    def __init__(self, S: str):
        self.root = Node()
        self._build_tree(S)
        
    def _build_tree(self, S: str):
        S += '$'
        n = len(S)
        for i in range(n):
            current = self.root
            for j in range(i, n):
                ch = S[j]
                if ch not in current.children:
                    current.children[ch] = Node()
                current = current.children[ch]
                current.idx_list.append(j - i)
                
    def longest_repeated_substring(self, k: int) -> str:
        max_len = 0
        max_str = ''
        for node in self.root.children.values():
            if len(node.idx_list) >= 2:
                node.idx_list.sort()
                for i in range(len(node.idx_list) - 1):
                    if node.idx_list[i + 1] - node.idx_list[i] >= k and node.idx_list[i] >= k and n - node.idx_list[i + 1] >= k:
                        length = node.idx_list[i + 1] - node.idx_list[i]
                        if length > max_len:
                            max_len = length
                            max_str = S[node.idx_list[i]:node.idx_list[i] + k]
        return max_str

以上就是三种解决该问题的方法,可以根据具体应用场景选择适合的算法。