以下思路中(prefix[x])代表桶的前缀和,其余不变。
目的是得到所有(suf_x)的排序。在这里考虑倍增玩法。
先把所有的(suf_x)按照(suf_x)的(ss[1])扔到桶里,对桶做前缀和。
对于拥有相同的(ss[1])的(suf_x),显然在他们的(rank)至少是(prefix[x[1]])
第一次对(suf_x)排序,大小为1,直接对(x)正着扫一遍,得到(rank)以后在桶的对应位置减掉。
现在有了第一轮排序的(rank)和(SA)
开始考虑倍增。
实际上就是合并长度为(len)的作为第一关键字的(suf_x)和作为第二关的(suf_{x+len})
现在有(n)个位置等你排序,作为关键字的(suf)长度是(siz)
发现从(n - siz + 1)这个位置开始,第二关键字都是空的
因此就得到排名为(i)的第二关键字 所属的第一关键字位置
现在考虑除了第二关键字为空的(suf)之外可以充当第二关键字的(suf)
发现如果一个(suf)所在的位置(i>siz),那么这个位置对应的第一关键字位置就是(i-siz)
因为获取第二关键字位置是递增的,于是可以扫(SA),同时判断(SA_i)位置来判断这个位置是否纳入第二关键字
现在获取了所有第二关键字及其对应第一关键字的位置。
当前所拥有的(x)实际上是上次排序后的,也就是仅仅以第一关键字为排名所得到的每个(suf_x)的排名。
然后扫(y_i),把对应(x_i)扔到桶里,然后对桶求前缀和
接着刷新(SA),但是不能直接考虑(SA_i)因为压根就求不出来
尝试用(y_i)来看看对(SA)的影响。
联系一下预处理时对(prefix)的操作,发现取得的排名是越来越小的,
也就是说,对于上一次排序拥有相同排名的第一关键字,应该倒着取第二关键字,以正确造成对桶对应位置的影响
所以得到了(SA[c[x[y[i]]]--]=y[i])
我们正确刷新了(SA),接着再来刷新(rank)。
很明显(x_i)也不能直接求,但是可以通过互相映射的已经刷新的(SA)来取得对应关系。
同时手头还有第二关键字。
对于排名相等的(SA_i)与(SA_{i-1})再比较第二关键字
因为要直接取得位置为(SA_i)的第二关键字,所以就是(SA_i+siz)直接使用第一关键字比较即可
如果相同那么获得相同排名,否则取得更大的排名。
对于每次刷新完以后,会有较多重复排名,因此可以通过每次刷新排名后最大排名(p)来更新桶的上界(m)
如果有(n)个不同排名或达到上界即停止排序。
取得的是每个位置(x)的(rank)和每个(rank)的位置(x),所以上文称互为映射。
性质
定义 (LCP(i,j))为(suf(SA[i]))和(suf(SA[j]))的最长公共前缀
LCP Base
对于一个(suf(SA[i]),)显然有(suf(SA[i-1]))或者是(suf(SA[i+1]))
使得其是使(suf(SA[i]))有最长(LCP)的可匹配(suf)
在(i<j<k)情况下首先有(LCP(i,j)geq LCP(i,k))
现在有若干(LCP)相关结论
LCP Lemma
1 : 固定(i,k)且(i<k,jin(i,k))时 (LCP(i,k)=min_{jin(i,k)}lbrace{LCP(i,j),LCP(j,k)} brace)
证明
定义 (p = min_{jin(i,k)}lbrace{LCP(i,j),LCP(j,k)} brace),
(q1 = suf(SA[i]), q2 = suf(SA[j]), q3 = suf(SA[k]))
此时(q1)和(q2),(q2)和(q3)的前(p)个字符相等,所以有(LCP(i,j)geq p)
那么(LCP(i,j) geq p, LCP(j,k) geq p),并且(q1[p + 1] eq q2[p+1])或(q2[p+1] eq q3[p + 1])
但是如果满足了(q1[p+1]=q3[p+1])且不满足上面两个条件中至少一个,就与(SA)的性质矛盾
所以得到(LCP(i,j)leq p) , 综上所述(LCP(i,j)=p)
其实也可以用(LCP Base)理解 因为要满足(forall jin(i,k) ,LCP(i,j)geq LCP(i,k))
所以(LCP = min_{jin(i,k)}lbrace{LCP(i,j),LCP(j,k)} brace)
LCP Theorem
2 : (LCP(i,k) = min_{jin[i,k)}lbrace{LCP(j,j+1)} brace)
证明 :
可以利用(LCP Lemma) 拆成(LCP(i,k) = min_{jin(i,k)}lbrace{LCP(i,i+1),LCP(i+1,k)} brace)的递归形式。
SA Height
定义(Height[i] = LCP(i, i - 1);i = 1)时明显有(Height[1] = 0,)(suf(i))的排名为(rk[i])
从(LCPspace Theorem)可以知道(LCP(i,k) = min_{jin(i,k]}{Height[j]})
定义(h[i] = Height[rk[i]])
现在有结论 : (h[i] geq h[i - 1] - 1)
如果排在(suf(i-1))前一个的是(suf(k)),
那分别删除首字符后就得到了(suf(i))和(suf(k+1))
因为(suf(k))本身排在(suf(i-1))前面,同时删除首字符以后一定还是排在前面
当然如果首字符不匹配,那么式子一定成立。
(suf(k))实际上是(suf(SA[rk[i-1]-1])),所以(LCP)即为(h[i-1])
同时删除首字符后得到的(LCP(k+1,i)=h[i-1]-1)
因为(suf(k+1))一定排在(suf(i))的前面,所以也一定包含了(suf(SA[rk[i]-1]))
又因为(SA[rk[i]-1]geq SA[rk[k+1]])
从而由(LCP Base)可以知道(h[i]geq h[i-1]-1)