如何在块排序中对数组后缀进行排序

时间:2011-06-14 23:45:42

标签: algorithm sorting suffix-array burrows-wheeler-transform

我正在阅读Burrows和Wheeler论文中的块排序算法。 这是算法的一个步骤:

假设S = abracadabra

初始化N个字W [0,...,N-1]的数组W,使得W [i]包含字符S'[i,...,i + k-1]这样排列使得对单词的整数比较与对k字符串的字典比较一致。将字符打包成单词有两个好处:它允许使用对齐的内存访问一次比较两个前缀k个字节,并且它允许消除许多慢速情况

(注意:S'是原始的S,附加了k EOF个字符,k是适合机器字符的字符数(我在32位机,所以k=4

EOF = '$'

如果我错了,请纠正我:

S'= abracadabra$$$$  
W= abra brac raca acad cada adab dabr abra bra$ ra$$ a$$$

然后,算法说你必须通过索引将S(名为V)的后缀数组排序 数组W

我不完全明白如何通过索引到W对后缀进行排序。 例如:在排序的某个时刻,假设您有两个后缀ij,您必须比较它们。由于您要编入W索引,因此您当时正在检查4个字符  假设它们具有相同的前4个字符。然后,您必须检查每个后缀的下4个字符,并通过访问W中每个后缀的第4个位置来执行此操作。 这是正确的吗?这种“将字符包装成文字”真的能加快速度吗?

2 个答案:

答案 0 :(得分:4)

您在问题中描述它的方式完全准确。是的,它会加快速度,因为就像你说的那样,它一次比较四个字符。

但有两点需要注意:

  1. 当你比较后缀i和j时,就像在你的例子中一样,你确实比较了条目W [i]和W [j]。这样的结果就像你按字母顺序比较四个字符S [i..i + 3]和S [j..j + 3],所以你节省了相当于三个字符比较的计算时间。是的,如果结果表明两个四元组是相同的,你必须继续比较W [i + 1]和W [j + 1],然而:你不要马上做。他们的算法的工作方式是基数排序。也就是说,你在初始比较之后立即将后缀放入桶中(可能两者都放在同一个桶中),然后递归地对桶进行内部排序。
  2. Burrows和Wheeler的原始论文中描述的算法(你引用它;例如,有一个副本here),它来自1994年,不是最优的后缀数组构造算法。首先,2003年发现了几种O(N)直接施工方法;其次,从那时起,对实施进行了许多进一步的改进。 1994年论文的核心是使用Burrows-Wheeler变换作为字符串压缩的基础,而不是变换本身生成的确切方式。

答案 1 :(得分:0)

数组V不是后缀数组,而是指向W的索引数组。一旦排序完成,V应该将索引保存到W中,这样如果

V[i] <= V[j]

然后

 W[V[i]] <= W[V[j]].

我希望我说对了:)让他们完全匹配不是问题,任何一个订单都没问题。关键是当你应用逆向转换时,你需要能够恢复W以恢复原始字符串,而W的相同元素不会导致问题。