我试图理解Karkkainen,P. Sanders的线性时间后缀数组创建算法的实现。可以找到算法的详细信息here。
我设法了解整体概念,但没有将其与提供的实施相匹配,因此无法清楚地理解它。
以下是令我困惑的初始代码路径。
根据论文:n0,n1,n2表示从i mod 3开始的三元组数=(0,1,2)
根据代码:n0 =(n + 2)/ 3,n1 =(n + 1)/ 3,n2 = n / 3; =>如何推导出这些初始化?
根据论文:我们需要创建T`,它是i mod 3中三元组的连接!= 0
根据代码:n02 = n0 + n2; s12 = [n02] ==>怎么来n02?它应该是n12,即n1 + n2。
根据代码:for(int i = 0,j = 0; i< n +(n0-n1); i ++)用三元组填充s12,使得i%3!= 0; =>为什么循环运行n +(n0 - n1)次?它应该只是n1 + n2。不应该吗?
由于这些原因我无法继续:(请求帮助。
答案 0 :(得分:2)
考虑以下示例,其中输入的长度为n = 13:
STA | CKO | WER | FLO | W
根据代码:n0 =(n + 2)/ 3,n1 =(n + 1)/ 3,n2 = n / 3; =>如何推导出这些初始化?
注意,如果n mod3 = 0,则三元组的数量i mod3 = 0是n / 3,否则为n / 3 + 1(如果n mod3 = 1或n mod3 = 2)。在当前示例中,n / 3 = 4但是从最后一个三元组开始,W' W'不完整它不计入整数除法。一个'技巧'直接进行这种计算就是使用(n + 2)/ 3。实际上,如果n mod3 = 0,那么整数除法(n + 2)/ 3和n / 3的结果将是相同的。但是,如果n mod3 = 1或2,那么(n + 2)/ 3的结果将是n / 3 + 1。这同样适用于n1和n2。
根据代码:n02 = n0 + n2; s12 = [n02] ==>怎么来n02?它应该是n12,即n1 + n2。 根据代码:for(int i = 0,j = 0; i< n +(n0-n1); i ++)用三元组填充s12,使得i%3!= 0; =>为什么循环运行n +(n0 - n1)次?它应该只是n1 + n2。应该不是吗?
这两个问题都有相同的答案。在我们的例子中,我们有一个像这样的B12缓冲区:
B12 = B1 U B2 = {TA KO ER LO}
因此,您首先对后缀进行排序,最后得到一个后缀数组B12,它有8个元素。为了进行合并步骤,我们首先需要计算B0的后缀数组,它是通过对元组进行排序(B0(i),rank(i + 1))得到的......但是这个具体情况是最后一个三元组有只有一个元素(W)有问题,因为没有为B0的最后一个元素定义rank(i + 1):
B0 = {0,3,6,9,12}
按字母顺序排序的导致
SA0 = {3, 9, 0, ?, ?}
由于索引6和12包含' W'因此按字母顺序排序是不够的,我们需要检查排名表中哪一个排在第一位,所以让我们检查排名他们的后缀..哦,等等! rank(13)未定义!
这就是为什么当最后一个三元组只包含一个元素时(如果n mod3 = 0),我们在输入的最后一个三元组中添加一个哑元0。那么B12的大小是n0 + n2,无论n1的大小如何,如果B0大于B1(在这种情况下n0-n1 = 1),则需要向B12添加一个额外的元素。
希望很清楚。