如何修改后缀数组以搜索多个字符串?

时间:2015-07-17 15:02:35

标签: algorithm list suffix-array

我最近一直在更新我的算法知识,并且一直在阅读后缀数组。我读过的每一篇文章都将它们定义为一个搜索字符串上的后缀数组,但有些文章提到了它的“琐碎”字样。推广到整个搜索字符串列表,但我不知道如何。

假设我尝试在单词列表上实现简单的子字符串搜索,并希望返回与给定子字符串匹配的单词列表。天真的方法似乎是插入字典结尾字符' $'在我的列表中的单词之间,将它们连接在一起,并从结果中生成后缀树。但这似乎会产生大量不相关的条目。如果我创建了一个来源于香蕉$松饼的源字符串'那么我最终会为“aa $ muffin”生成后缀' ana $ muffin'我永远不会使用它。

我很欣赏任何有关如何正确执行此操作的提示,或者更好的是指向处理此案例的某些算法文本的指针。

3 个答案:

答案 0 :(得分:0)

在Suffix-Arrays中,你通常不使用字符串,只使用一个字符串。这将是几个字符串的连接版本,其中有一些是endtoken(每个字符串都有一个不同的字符串)。对于后缀数组,您可以使用指针(或数组索引)来引用后缀(仅需要第一个标记/字符的位置)。 所以所需的空间是每个后缀指针的数组+。 (这只是一个非常简单的实现,你应该做更多,以获得更多的性能)。

在这种情况下,您可以优化后缀的排序算法,因为您只需要对指针引用的后缀进行排序,直到结束。 endtoken背后的所有内容都不需要在排序算法中使用。

答案 1 :(得分:0)

现在阅读Dan Gusfield撰写的大部分关于字符串,树和序列的算法之后,答案似乎很清楚。

如果您从多字符串后缀树开始,其中一个标准转换算法仍然有效。但是,您最终得到的是一系列列表,而不是获取整数数组。每个列表包含一对或多对字符串标识符以及该字符串中的起始偏移量。

结果结构仍然有用,但效率不如普通的后缀数组。

答案 2 :(得分:0)

来自爱荷华州立大学,摘自 Prefix.pdf

<块引用>

后缀树和后缀数组可以推广到多个字符串。 一组字符串的广义后缀树 S = {s1, s2, ... . . , sk},表示为 GST(S) 或简称 GST,是所有后缀的压缩树 S 中的每个字符串。我们假设唯一的终止符 $ 附加到每个字符串的末尾。叶标签现在由一个 一对整数 (i, j),其中 i 表示后缀来自字符串 si j 表示 si 中后缀的起始位置。相似地, GST 中的边标签是其中一个字符串的子字符串。一个边缘 标签由一组整数 (i, j, l) 表示,其中 i 表示字符串编号,j 和 l 表示开始和结束 si 中子串的位置。为方便理解, 我们将继续显示实际的边缘标签。注意两个字符串 可能有相同的后缀。这是通过允许叶子进入来补偿的 树有多个标签。如果一片叶子被多重标记,每个 后缀应该来自不同的字符串。如果 N 是总数 S 中所有字符串的字符数(包括每个字符串中的 $), GST 最多有 N 个叶子节点,占用 O(N) 空间。这 S 的广义后缀数组,表示为 GSA(S) 或简称为 GSA,是一个 S 中每个字符串的所有后缀的按字典序排序的数组。 每个后缀由表示后缀的整数对 (i, j) 表示 从 si 中的位置 j 开始。如果后缀来自不同的字符串 相同,它们在 GSA 中占据连续的位置。为了 为方便起见,我们对后缀 $ 进行了例外处理,仅列出它 一次,尽管它出现在每个字符串中。字符串的 GST 和 GSA 苹果和枫树如图1.2所示。

这里有一篇关于构建 GSA 的算法的文章:

Generalized enhanced suffix array construction in external memory