DC3算法模板学习笔记

    今天看了一下洛谷sx视频,后缀数组双关键字排序瞬间秒懂,昨天刚了一下午没有看懂的后缀数组基数排序代码有了一点点突破。
    对第二关键字桶排序,保持相对顺序不变,则个位数字有序,对第一关键字桶排序,由于第一关键字相同情况下个位总是递增或持平,所以保持有序。 
    ——《高级数据结构》
#include
#include
using namespace std;
//获取后缀数组中对应后缀的原本位置
#define GetRealPos()
{
SA12[pos12]<0?SA12[pos12]*3+1:(SA12[pos12]-n0)*3+2)
}
//二元组的排序比较 
inline bool cmp(int a1,int a2,int b1,int b2)
{
	return (a1

DC算法
DC3算法是DC算法的特殊情况。DC算法的后缀采样方式是选取呢些后缀位置模3不为0的后缀,因此,我们通过将该采样过程一般化,从而得到DC(Difference Cover modulov)算法。也就是说,DC3是v=3的情形。接下来,我们将和DC3算法一样一步一步进行构建,读者可以对两个算法进行对比。
步骤一:采样
定义集合D属于[0,v),D满足{(i-j)mod v|i,j属于D}=[0,v)。
类似DC3的定义,有Bk={i|i属于[0,n]且i mod v=k},其中k属于[0,v)。那么,采样集合C现在为:C=Uk属于DBk.
步骤二:构建后缀采样集合的后缀数组
对于Rk,现在我们没v个字符一组形成新的“字符”:Rk=[tktk+1…tk+v-1] [tk+tk+v+1…tk+2v-1]…直到T的末尾。
同样,定义R为所有Rk首尾相接的结果。利用基数排序和递归,我们同样可以得到被采样后缀的后缀数组,类似DC3。
步骤三 计算未被采样的后缀数组名次
令D=[0,v)-D,则同样被采样集合为C=Uk属于DBk。对某个k属于D,我们单独对后缀集合Suffix(Bk)进行排序。这一步与DC3中有一些小的区别:我们需要找到一个l,使得(k+l)mod v属于D。这样做是为了找到L元组来表示从位置i开始的后缀(ti,ti+1,…ti+l-1,Rank(Suffix(i+l))),可见,如果Rank(Suffix(i+l))已知,等价于(i+l) mod v属于D,同时注意i mod v=k,因此l需要满足(k+l) mod v属于D。
现在需要证明的是上述l一定存在。根据定义,对k属于[0,v),存在i,j属于D,使得(i-j)同余于k(mod v),令l为j,则有(k+l)同余于i(mod v),得证。这里对于每个k,使对应的l可以首先预处理出来。
由于存在有D个未被采样的后缀集合,故上述算法需要执行D次。

步骤四:合并若干个名次数组
现在面对的问题不是二路归并了,而是多路归并。如果用DC3同样的比较方式进行合并的话,至少需要O(nvlog2v)的时间复杂度,所以需要换一个思路。
首先,将被采样后缀分成D个有序集合,即对k属于D,将后缀集合Suffix(Bk)分离出来变成有序的。因为已经处理出了Suffix©,所以上述过程可以在线性时间复杂度内完成。至此,我们得到了v个有序后缀集合。接下来进一步将后缀根据其第一个“字符”(即v元组,见步骤二)进行分类。也就是说,首先根据k的值将后缀分成k个集合,接下来根据第一个“字符”进一步对每个集合细分,同时,每个集合内部又是有序的。假设Suffix(Bk,a)为集合Suffix(Bk)中首“字符”为a的后缀集合,那么我们通过细分,得到的结果类似于:
Suffix(B0,a),Suffix(B1,a)…Suffix(Bv-1,a),Suffix(B0,b)…
不难发现,上述过程同样可以在线性时间复杂度内完成。这样做的好处在以下合并过程中就体现出来了——对于每个“”字符”a,我们合并集合Suffix(B0,a),Suffix(B1,a)…,Suffix(Bv-1,a)成为一个有序集合。如果这一步完成,那么接下来只需要根据首“字符”进一步合并,即得到所需要的后缀数组了。假设当前合并首“字符”为a的那些集合,对于两个待比较的后缀Suffix(i)和Suffix(j),我们找到这样的l,使得(i+l) mod v属于D且(j+l) mod v属于D,有了步骤三的证明,这样的l一定可以找到。所以Rank(i+l)和Rank(j+l)是可比较的。进一步,由于Suffix(i)和Suffix(j)具有相同的首字母a,所以它们的序关系就等价于Rank(i+l)与Rank(j+l)的序关系。至此,有了比较函数之后就可以对集合进行合并了。
类似于DC3算法的时间复杂度证明,这里递归式的规模也是衰减的。由于v的存在,最后的时间复杂度实际上为O(nv).
该算法的意义在于,通过恰当的实现方式,可以将除了输入,输出空间以外的额外空间复杂度降到O(n
v的1/2)。参考论文研究。介绍DC算法的目的是为了能够较全面的看待DC3算法并了解它是DC算法的特殊情况,通过两者相互比较对DC3算法有较好的认识。

你可能感兴趣的:(acm)