首先必定要肯定\(SA\)是个什么东西
\(SA[i]\)表示的是排名为\(i\)的后缀是哪个
至于后缀\(i\)的排名是多少,那个是\(rank[i]\)数组
固然啦
最最最难懂的就是基数排序
要是不用基数排序,每次对于一个二元组直接\(sort\)一下
这样的复杂度是\(O(nlog^2)\)spa
对于二元组的基数排序应该是这样作的:
首先把全部元素按照最后一维丢到依次对应的桶里面
而后顺次取出
再按照第一维依次丢入
再顺次取出
这样就能够排序啦code
先把代码丢出来排序
bool cmp(int i,int j,int k){return y[i]==y[j]&&y[i+k]==y[j+k];} void GetSA() { int m=30; for(int i=1;i<=n;++i)t[x[i]=a[i]]++; for(int i=1;i<=m;++i)t[i]+=t[i-1]; for(int i=n;i>=1;--i)SA[t[x[i]]--]=i; for(int k=1;k<=n;k<<=1) { int p=0; for(int i=0;i<=m;++i)y[i]=0; for(int i=n-k+1;i<=n;++i)y[++p]=i; for(int i=1;i<=n;++i)if(SA[i]>k)y[++p]=SA[i]-k; for(int i=0;i<=m;++i)t[i]=0; for(int i=1;i<=n;++i)t[x[y[i]]]++; for(int i=1;i<=m;++i)t[i]+=t[i-1]; for(int i=n;i>=1;--i)SA[t[x[y[i]]]--]=y[i]; swap(x,y); x[SA[1]]=p=1; for(int i=2;i<=n;++i)x[SA[i]]=cmp(SA[i],SA[i-1],k)?p:++p; if(p>=n)break; m=p; } }
首先,第一次作\(k=0\)时
至关于每一个后缀的第二维都是同样的
因此,直接按照第一维(也就是本身的值)
进行一次基数排序class
接下来
每次基数排序都要利用到上一次的值sort
还记得吧,基数排序是先按照第二维从小往大拍
那么,咱们就先把第二维的顺序搞出来
首先最小的必定就是没有第二维的东西
因此咱们先把这些数直接丢进数组里面
接下来就是有第二维的东西啦
第\(i\)位的第二维是啥?\(rank[i+k]\)
因此,从小到达枚举\(SA\),这样保证第二维从小往大
那么,只要\(SA[i]>k\)
就证实它是一个东西的第二维
因此,把\(SA[i]-k\)丢到数组里面去就好啦while
这样的话,按照第二维就拍好啦
再来依次按照第一维丢到桶里面去
作一遍基数排序就好啦
这样就可以求出\(SA\)啦co
看起来很简单诶。。
只是数组不要搞混了
必定搞清楚每一个数组是干啥的
好比个人代码
\(SA\)是后缀数组,\(SA[i]\)表示排名为\(i\)的串是哪个
\(rank\)至关于排名,\(rank[i]\)表示第\(i\)个串的排名
\(x,y\)两个数组是记录顺序的
分别记录第一维和第二维的排序的顺序
\(t\)是桶字典
这样咱们就很愉快的求出了\(SA\)
还有一个数组\(Height\)
\(Height[i]\)表示串\(SA[i]\)与\(SA[i-1]\)的最长公共前缀的长度
好比说,如今要求后缀\(i\)与\(j\)的最长公共前缀
那就只须要求\(min(Height[i]),i \in [rank[i]+1,rank[j]]\)
由于已经按照字典序排好序啦block
\(Height\)显然能够暴力求
可是太不优美
咱们有\(Height[rank[i]]>=Height[rank[i-1]]-1\)
证实(来自\(hihoCoder\))
设\(suffix(k)\)是排在\(suffix(i-1)\)前一名的后缀,
则它们的最长公共前缀是\(height[rank[i-1]]\)
那么\(suffix(k+1)\)将排在\(suffix(i)\)的前面(这里要求\(height[rank[i-1]]>1\),若是\(height[rank[i-1]]≤1\),原式显然成立)
而且\(suffix(k+1)\)和\(suffix(i)\)的最长公共前缀是\(height[rank[i-1]]-1\),
因此\(suffix(i)\)和在它前一名的后缀的最长公共前缀至少是\(height[rank[i-1]]-1\)
那么,咱们按照\(rank\)的顺序来求\(Height\)就行啦
for(int i=1;i<=n;++i)Rank[SA[i]]=i; for(int i=1,j=0;i<=n;++i) { if(j)j--; while(a[i+j]==a[SA[Rank[i]-1]+j])++j; height[Rank[i]]=j; }
我如今也不是很熟 之后多作点题我再接着补