【问题标题】:How to reverse a suffix tree of a string (findind the string it represents)如何反转字符串的后缀树(找到它所代表的字符串)
【发布时间】:2015-03-11 10:27:53
【问题描述】:

给定一个(修改/损坏的)后缀树,它在每条边存储当前子串的开始和结束,但不存储子串本身,即后缀树如下所示:

这棵树代表字母表中的字符串“香蕉”:{a, b, n}。

我正在寻找的算法是找到那种树代表的字符串,对于上面的例子,我希望算法找到“香蕉”。 我想在 O(|string|) 的复杂度中使用 |string|是正在搜索的字符串的长度。 可以假设:

字母的大小是恒定的,每个字符串都从索引 1 开始。

【问题讨论】:

  • 你说的损坏的后缀树是什么意思?

标签: string algorithm data-structures suffix-tree


【解决方案1】:
  1. 让我们从一些多项式时间解决方案开始:

    • 让我们将字符串中的所有字符划分为等价类。

    • 我们已经知道:这是一个特殊的$ 符号。

    • 归纳假设:假设我们已将长度为k 的后缀的所有字符正确划分为等价类。对于长度为k + 1的后缀,我们也可以做到。

    • 证明:让我们遍历所有长度为i <- 1...k 的后缀,并检查长度为k 的后缀和长度为i 的后缀的最长公共前缀的长度是否不为零。如果相应叶子的最低共同祖先不是树的根,则它是非零的。如果我们找到了这样的后缀,我们就知道它的第一个字母等于当前后缀的第一个字母。所以我们可以将长度为k + 1的后缀的第一个字母添加到适当的等价类中。否则,它属于它自己的等价类。

    • 当所有字符被划分为等价类时,我们只需要为每个类分配一个唯一的符号(如果我们需要保持正确的字典顺序,我们可以检查其中哪个更早。 ,我们需要查看从根开始的边的顺序)。

    • 时间复杂度是O(n ^ 3)(有n 就足够了,我们迭代O(n) 其他就足够了,我们在O(n) 中计算它们的lca(我假设我们使用一个幼稚的算法在这里))。到目前为止,一切顺利。

  2. 现在让我们使用几个观察得到一个线性解:

    • 我们真的不需要 lca。我们只需要检查它是否不是根。因此,我们可以根据它们的祖先(即根的直接子代)将所有叶子划分为等价类。它可以使用深度优先搜索在线性时间内完成。两个后缀的最长公共前缀是非空的,如果它们在同一个类中。

    • 我们实际上并不需要检查所有较短的内容。我们只需要在深度优先搜索顺序中检查左边和右边最近的一个。从给定的左侧和右侧找到最接近的较小数字是一个标准问题,它有一个带有堆栈的线性解决方案。

    • 就是这样:对于给定的一个,我们最多检查另外两个足够,每个检查是O(1)。我们现在有一个线性解决方案。

此解决方案使用这样的字符串确实存在的假设。如果这个假设不可行,我们可以使用这个算法构造一些​​字符串,然后使用 Ukkonnen 算法为它构建一个线性的后缀树,并检查它是否与给定的完全相同。

【讨论】:

    猜你喜欢
    • 2013-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-06
    • 2023-03-28
    • 2013-05-10
    • 2016-01-06
    相关资源
    最近更新 更多