【问题标题】:Longest repeated substring with at least k occurrences correctness至少出现 k 次的最长重复子串 正确性
【发布时间】:2016-11-15 14:58:01
【问题描述】:

寻找最长重复子串的算法公式如下 1)build the suffix tree 2)find the deepest internal node with at least k leaf children 但我不明白为什么这是有效的,所以基本上是什么让这个算法正确?另外,我发现这个算法的来源说是找到重复的O(n) 中的子串,其中 n 是子串的长度,这对我来说也不清楚!让我们考虑下面的树,这里最长的重复子串是“ru”,如果我们应用 DFS,它将在 5 中找到它步但不在 2 你能给我解释一下这些东西吗? 谢谢

image

【问题讨论】:

  • 它不能在子串的长度上是线性的,因为后缀树结构在字符串本身的长度上是线性的

标签: string algorithm suffix-tree suffix-array longest-substring


【解决方案1】:

我想你完全知道O(n)(大 O 表示法)指的是作为 n 函数的某个数量的 增长顺序,而不是等价于n 的数量。
我写这篇文章是因为阅读了我有疑问的问题...
我写这篇文章是作为一个回答而不是评论,因为评论有点太长了(我想......)

【讨论】:

    【解决方案2】:

    给定一个N个字符的字符串S,构建对应的后缀树为O(N)(使用@987654321等算法@)。

    现在,这样的后缀树可以有at most 2N - 1 nodes(包括根和叶)。

    如果您遍历您的树并计算从给定节点可到达的叶子数量及其深度,您会找到所需的结果。为此,您需要从根开始并探索其每个子项。

    一些伪代码:

    traverse(node, depth):
        nb_leaves <-- 0
        if empty(children(node)):
            nb_leaves <-- 1
        else:
            for child in children(node):
                nb_leaves <-- nb_leaves + traverse(child, depth+1)
        node.setdepth(depth)
        node.setoccurrences(nb_leaves)
        return nb_leaves
    

    初始呼叫是traverse(root, 0)。由于结构是一棵树,因此每个节点只调用一次traverse。这意味着对traverse 的最大调用次数为2N - 1,因此整体遍历只有O(N)。现在您只需通过添加相关的簿记机制来跟踪具有最大深度的节点即可验证:depth &gt; 0 &amp;&amp; nb_leaves &gt;= k。这并不妨碍整体的复杂性。

    最后,找到这样一个子字符串的算法复杂度是 O(N) 其中 N 是输入字符串的长度(而不是长度匹配的子字符串!)。

    注意:上面说的遍历基本上就是后缀树上的一个DFS。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-29
      • 2021-10-27
      • 2011-10-02
      • 1970-01-01
      • 1970-01-01
      • 2020-11-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多