String 最长循环子串
这是一个关于Jon Bentley的“编程珍珠”中描述的最长循环子串算法的问题。我记得,他们为输入字符串构建一个后缀数组,对后缀进行排序,然后扫描它们 看起来最昂贵的步骤是排序。如果我们使用比较排序,那么比较的数量是O(N*logN),其中N是输入字符串的大小。因为字符串比较是O(字符串长度),所以排序是O(N^2) 这有意义吗String 最长循环子串,string,algorithm,sorting,String,Algorithm,Sorting,这是一个关于Jon Bentley的“编程珍珠”中描述的最长循环子串算法的问题。我记得,他们为输入字符串构建一个后缀数组,对后缀进行排序,然后扫描它们 看起来最昂贵的步骤是排序。如果我们使用比较排序,那么比较的数量是O(N*logN),其中N是输入字符串的大小。因为字符串比较是O(字符串长度),所以排序是O(N^2) 这有意义吗 因此,算法在空间中是O(N^2)和O(N)。它能做得更好吗?简单的排序会使后缀数组构造为O(n^2logn),而不是O(n^2) 然而,在O(n)中有构造后缀数组的方法
因此,算法在空间中是O(N^2)和O(N)。它能做得更好吗?简单的排序会使后缀数组构造为O(n^2logn),而不是O(n^2) 然而,在O(n)中有构造后缀数组的方法[一种简单的方法是构造后缀树并将其转换为后缀数组-后缀树构造为O(n)]
我不知道一个人是否可以用小于O(n)的空间来做。虽然可以从后缀树构造后缀数组,但这没有什么意义。它将消除后缀数组的主要优点(除了一般的简单性):内存消耗小 有一种简单的方法可以对
O(n*logn)
time中的后缀数组进行排序。(由于这个原因,它经常被用于各种算法竞赛中,以替代复杂的后缀尝试)
基本思路如下。我们将分阶段对后缀进行排序,在阶段i
(i=0,1,2,3,
)中只考虑每个后缀的第一个2^i
字符
按后缀的第一个字符排序很简单,对您来说应该没有问题。在这个(“第0个”)阶段之后,我们将有一个部分排序的后缀数组和另一个数组,其中包含将后缀划分为多个存储桶:每个存储桶包含具有相同第一个符号的后缀
现在,假设我们已经完成了阶段i
,现在处理阶段i+1
。我们需要比较属于同一个bucket的两个后缀s(t)
和s(q)
。(让s(t)
成为原始字符串中从位置t
开始的后缀。)因为第一个<代码> 2 ^ i /代码>字符是相同的,所以我们只需要考虑下一个<代码> 2 ^ i /代码>字符(因此,总数将是代码>2 ^(i +1)< /代码>)。但是后缀
s(t)
没有它的第一个2^i
符号是s(t+2^i)
。因此,我们只需要根据它们的第一个2^i
符号来比较s(t+2^i)
和s(q+2^i)
,我们已经从阶段i
获得了这些信息
结束。第一次实现它可能有点棘手(这也是一个很好的练习),但这就是想法。请注意,从原始字符串读取实际字符的唯一时间是步骤0
。然后,在步骤i
,我们只使用步骤i-1
的结果
编辑详细介绍了这个想法。(IMHO表示,要理解it需要的细节要多得多,实现要比需要的复杂得多。)