请解释:
假设我们有一个对应于n字符文本的后缀数组,我们想要在m字符模式的文本中找到所有出现的内容。由于后缀是有序的,最简单的解决方案是使用O(log n)比较对模式的第一次和最后一次出现(如果有的话)进行二进制搜索。
在确定模式的第一次和最后一次出现后,我需要知道如何才能获得所有出现的模式。
答案 0 :(得分:1)
你引用的文字有两点令人困惑,甚至可能有误导性:
它说找到模式的第一个和最后一个出现就足够了,但应该更准确地说:后缀数组中的第一个和最后一个出现。这与基础文本中第一次和最后一次出现的情况不同。
它说你需要进行O(log n)比较。仅当“比较”指的是最多m个字符的字符串比较时,才会出现这种情况。由于比较多达m个字符需要O(m)时间,因此计算步骤的数量(例如在标准RAM模型中)是O(m * log n)。如果构建和使用辅助数据结构,例如LCP(最长公共前缀)数组,则可以改进它。
现在,回答您的问题:考虑上面的(1.),您可以轻松地获得所有模式,因为后缀数组按字典顺序排序。这意味着第一次出现的是字典上最小的,最后出现的是字典上最大的。因此,剩余的事件必须介于之间的第一个和最后一个。
示例。考虑字符串bcfabcabxbbcabcgdebcd
。它的后缀数组(表示为后缀的起始位置,从0开始计数)是
[3, 12, 6, 9, 10, 4, 18, 0, 13, 7, 11, 5, 19, 1, 14, 20, 16, 17, 2, 15, 8]
对应于以下后缀列表:
3 : abcabxbbcabcgdebcd
12 : abcgdebcd
6 : abxbbcabcgdebcd
9 : bbcabcgdebcd
10 : bcabcgdebcd <======= first occurrence of 'bc'
4 : bcabxbbcabcgdebcd
18 : bcd
0 : bcfabcabxbbcabcgdebcd
13 : bcgdebcd <======= last occurrence of 'bc'
7 : bxbbcabcgdebcd
11 : cabcgdebcd
5 : cabxbbcabcgdebcd
19 : cd
1 : cfabcabxbbcabcgdebcd
14 : cgdebcd
20 : d
16 : debcd
17 : ebcd
2 : fabcabxbbcabcgdebcd
15 : gdebcd
8 : xbbcabcgdebcd
假设您要寻找的模式是'bc'。我在后缀数组中标记了该模式的第一次和最后一次出现。由于词典排序,其间的所有条目也必须以'bc'开头,任何以'bc'开头的条目必须介于两者之间。因此,所有以'bc'开头的后缀,即'bc'出现的所有位置,必须介于第一次和最后一次出现之间。
表示为位置整数,我们确定的范围是
[10, 4, 18, 0, 13]
因此,位置10,4,18,0和13标记了模式的出现。
(注意,实际上不使用后缀的完整字符串列表 - 只使用整数位置列表。)