首页 > 其他 > 详细

SA整理

时间:2019-10-08 23:39:36      阅读:174      评论:0      收藏:0      [点我收藏+]

果然\(SA\)这种东西是精益求精。

梳理一下大致思路。

以下思路中\(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,j\in(i,k)\)\(LCP(i,k)=min_{j\in(i,k)}\lbrace{LCP(i,j),LCP(j,k)}\rbrace\)

证明

定义 \(p = min_{j\in(i,k)}\lbrace{LCP(i,j),LCP(j,k)}\rbrace\),

\(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] \neq q2[p+1]\)\(q2[p+1]\neq q3[p + 1]\)

但是如果满足了\(q1[p+1]=q3[p+1]\)且不满足上面两个条件中至少一个,就与\(SA\)的性质矛盾

所以得到\(LCP(i,j)\leq p\) , 综上所述\(LCP(i,j)=p\)

其实也可以用\(LCP Base\)理解 因为要满足\(\forall j\in(i,k) ,LCP(i,j)\geq LCP(i,k)\)

所以\(LCP = min_{j\in(i,k)}\lbrace{LCP(i,j),LCP(j,k)}\rbrace\)

LCP Theorem

2 : \(LCP(i,k) = min_{j\in[i,k)}\lbrace{LCP(j,j+1)}\rbrace\)

证明 :

可以利用\(LCP Lemma\) 拆成\(LCP(i,k) = min_{j\in(i,k)}\lbrace{LCP(i,i+1),LCP(i+1,k)}\rbrace\)的递归形式。

SA Height

定义\(Height[i] = LCP(i, i - 1);i = 1\)时明显有\(Height[1] = 0,\)\(suf(i)\)的排名为\(rk[i]\)

\(LCP\space Theorem\)可以知道\(LCP(i,k) = min_{j\in(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\)

SA整理

原文:https://www.cnblogs.com/cjc030205/p/11638100.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!