【问题标题】:How to find longest common substring using trees?如何使用树找到最长的公共子串?
【发布时间】:2012-06-15 18:37:15
【问题描述】:

根据 wiki 的最长公共子串问题可以使用后缀树来解决。
来自wiki

一组字符串的最长公共子串可以通过 为字符串构建一个通用的后缀树,然后找到 具有来自所有字符串的叶节点的最深内部节点 在它下面的子树中

我不明白。
示例:如果我有:
ABCDEXABCZ
那么后缀树是(XABCZ 的一些分支由于空格而省略):

最长的公共子字符串是ABC,但不是我看不到wiki的描述在这里有什么帮助。
ABC不是最深的内部节点与叶节点。
对理解这是如何工作的有帮助吗?

【问题讨论】:

  • ABC is not the deepest internal nodes with leaf nodes. 不,但是 ABC 树中任何地方最长的 common 节点字符串。下一个最长的是B-CD-E,每个都有两个节点。
  • 是的 ABC 是最长的公共字符串。但我不明白 wiki 描述实际上如何帮助我以编程方式找到它
  • 您必须阅读另一个 Wiki:en.wikipedia.org/wiki/Generalised_suffix_tree。可能有一些更好(更容易理解)的资源here。另见stackoverflow.com/questions/969448/…
  • @user384706 - 我认为部分问题在于这不是正确的后缀树。您应该只有一个以根 A-B-C 开头的分支,而 C 将有两个孩子:D-E 和 Z。其余分支类似。你所拥有的基本上只是一个后缀列表,它们都有一个指向它们的根节点。
  • @twalberg:是的,你是对的。 2 个蓝色分支将是一个。但在这种情况下,我如何以编程方式找到它们?我不清楚 wiki 描述有什么帮助

标签: java algorithm data-structures tree substring


【解决方案1】:

就像之前所说的,你的树是不正确的。

这是通过我的代码运行“ABCDE$XABCZ”时得到的结果。

Suffix Tree code:

String = ABCDE$XABCZ$
End of word character 1 = $
└── (0)
    ├── (20) $
    ├── (22) ABC
    │   ├── (15) DE$
    │   └── (23) Z$
    ├── (24) BC
    │   ├── (16) DE$
    │   └── (25) Z$
    ├── (26) C
    │   ├── (17) DE$
    │   └── (27) Z$
    ├── (18) DE$
    ├── (19) E$
    ├── (21) XABCZ$
    └── (28) Z$

在(紧凑)后缀树中,您需要从所有字符串中找到具有叶节点的最深内部节点。如果在同一深度有多个节点,则必须比较该节点表示的字符串的长度。即 ABC、BC 和 C 都具有相同的深度,因此您必须比较 ABC、BC 和 C 字符串的长度,看看哪个更长;这显然是ABC。

Suffix Trie code:

└── null
    ├── A
    │   └── B
    │       └── C
    │           ├── D
    │           │   └── (E) ABCDE
    │           └── (Z) ABCZ
    ├── B
    │   └── C
    │       ├── D
    │       │   └── (E) BCDE
    │       └── (Z) BCZ
    ├── C
    │   ├── D
    │   │   └── (E) CDE
    │   └── (Z) CZ
    ├── D
    │   └── (E) DE
    ├── (E) E
    ├── X
    │   └── A
    │       └── B
    │           └── C
    │               └── (Z) XABCZ
    └── (Z) Z

在一个(非紧凑的)后缀树中,从所有字符串中找到最深的内部节点,该节点具有叶节点。

希望对你有帮助。

【讨论】:

  • 这是一个“折叠”的后缀树吗?还有什么数字,例如(20)(24) 等?
  • 是的,这是折叠的,但是折叠意味着合并,例如“DE” 为单个节点。然而,所有后缀树都会将“CDE$”和“CZ$”组合成一个带有“DE$”分支和“Z$”分支​​的“C”节点——但折叠后缀树会处理“DE$”作为一个节点,未折叠的后缀树会将“DE$”视为三个节点,每个字符一个。
  • @user384706 是的,这是一棵倒塌的树。这些数字只是节点标识符,没有什么要注意的。如果您有兴趣,我还创建了一个后缀树。我将其添加到答案中。
【解决方案2】:

您实际上还没有绘制后缀树。如果你做得正确,从根本上你只会拥有每个可能的角色一次。仅当单个字母可以具有多个后续后缀时,树才会分裂。这会在树中强制将公共子字符串放在一起,从而使它们可以被找到。

【讨论】:

  • 我不确定我是否在这里关注你。如果字符串是:ABCDBEF,那么在B 下会有一个子分支,用于BCDBEFBEF,但是对于这个例子,即ABCDE,我们不会为每个可能的后缀都有一个分支吗?
  • 在您给出的示例图中,最多应该有一个标记为“A”的根的孩子。您应该已经合并了这两个节点。
  • @LouisWasserman:真的吗?为什么?AABCDE 中的前缀。为什么会有一个root的子节点A
  • 后缀树的全部意义在于将匹配的后缀前缀合并到同一个根中。根应该有一个分支到ABC,然后最后一个节点应该有两个孩子,一个X和一个DE
  • @LouisWasserman:好的。我同意。但在这种情况下,即拥有 2 个合并节点,我如何使用 wiki 描述以编程方式找到最长的公共子字符串?我被困在这个
猜你喜欢
  • 2015-06-23
  • 2012-05-02
  • 1970-01-01
  • 1970-01-01
  • 2012-10-07
  • 1970-01-01
  • 2014-04-14
  • 2014-04-16
  • 2014-01-17
相关资源
最近更新 更多