如何使用树找到最长的公共子串?
Posted
技术标签:
【中文标题】如何使用树找到最长的公共子串?【英文标题】:How to find longest common substring using trees? 【发布时间】:2012-06-15 18:37:15 【问题描述】:根据 wiki 的最长公共子串问题可以使用后缀树来解决。 来自wiki:
一组字符串的最长公共子串可以通过 为字符串构建一个通用的后缀树,然后找到 具有来自所有字符串的叶节点的最深内部节点 在它下面的子树中
我不明白。
示例:如果我有:ABCDE
和 XABCZ
那么后缀树是(XABCZ
的一些分支由于空格而省略):
最长的公共子字符串是ABC
,但不是我看不到wiki的描述在这里有什么帮助。ABC
不是最深的内部节点与叶节点。
对理解这是如何工作的有帮助吗?
【问题讨论】:
ABC is not the deepest internal nodes with leaf nodes.
不,但是 ABC 是树中任何地方最长的 common 节点字符串。下一个最长的是B-C
和D-E
,每个都有两个节点。
是的 ABC
是最长的公共字符串。但我不明白 wiki 描述实际上如何帮助我以编程方式找到它
您必须阅读另一个 Wiki:en.wikipedia.org/wiki/Generalised_suffix_tree。可能有一些更好(更容易理解)的资源here。另见***.com/questions/969448/…
@user384706 - 我认为部分问题在于这不是正确的后缀树。您应该只有一个以根 A-B-C 开头的分支,而 C 将有两个孩子:D-E 和 Z。其余分支类似。你所拥有的基本上只是一个后缀列表,它们都有一个指向它们的根节点。
@twalberg:是的,你是对的。 2 个蓝色分支将是一个。但在这种情况下,我如何以编程方式找到它们?我不清楚 wiki 描述有什么帮助
【参考方案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
下会有一个子分支,用于BCDBEF
和BEF
,但是对于这个例子,即ABCDE
,我们不会为每个可能的后缀都有一个分支吗?
在您给出的示例图中,最多应该有一个标记为“A”的根的孩子。您应该已经合并了这两个节点。
@LouisWasserman:真的吗?为什么?A
是ABCDE
中的前缀。为什么会有一个root的子节点A
?
后缀树的全部意义在于将匹配的后缀前缀合并到同一个根中。根应该有一个分支到ABC
,然后最后一个节点应该有两个孩子,一个X
和一个DE
。
@LouisWasserman:好的。我同意。但在这种情况下,即拥有 2 个合并节点,我如何使用 wiki 描述以编程方式找到最长的公共子字符串?我被困在这个以上是关于如何使用树找到最长的公共子串?的主要内容,如果未能解决你的问题,请参考以下文章