后缀排序

后缀排序

本文做复习用,不宜初学用。
注意排序顺序

定义

sa 表示排名为 i 的位置。

rk 表示位置为 i 的排名。

y 表示按照第二关键字排序排名为 i 的位置。

height 表示排名为 ii1 的后缀的最大前缀

h 表示位置为 i 和它排名前一位的后缀的最大前缀

操作流程

最初字符串排序

这里是桶排序基础操作。

for(int i = 1; i <= n; ++i) ++c[rk[i] = a[i]];
for(int i = 1; i <= m; ++i) c[i] += c[i - 1];
for(int i = n; i >= 1; ++i) sa[c[rk[i]--] = i;//按照1,2,3的顺序排

为什么是倒叙的呢?你用手模拟一下ababa这个样例就懂了

进行倍增比较操作。

for(int i = 1; i <= n; i <<= 1)

第二关键字排序

这里是把最后那一部分没有第二关键字的放在最前面。

num = 0;
for(int i = n - k  + 1; i <= n; ++i) y[++num] = i;

对有第二关键字的排序。按照 sa 数组,也就是排名进行。

for(int i = 1; i <= n; ++i) if(sa[i] - k > 0) y[++num] = sa[i] - k;

总体排序

清空桶。

for(int i = 1; i <= m; ++i) c[i] = 0;

这里先按照 rk 排序,和最初字符串排序有点类似。

for(int i = 1; i <= n; ++i) ++c[rk[i]];
for(int i = 1; i <= m; ++i) c[i] += c[i - 1];
for(int i = n; i >= 1; --i) sa[c[rk[y[i]--] = y[i];//按照y[i]的顺序排

更新 rk 数组和 m

这里把 yrk 交换其实就是用 y 暂时存储上一次的 rk

比较当前 sa[i]sa[i1] 是否完全相等。如果相等就和 sa[i1] 赋一样的 num

swap(rk,y);num = 0;
for(int i = 1; i <= n; ++i)
    rk[sa[i]] = (y[sa[i]] == y[sa[i - 1]] && sa[i] + k <= n && sa[i - 1] + k <= n && y[sa[i] + k] == y[sa[i - 1] + k]) ? num : ++num;
if(num == n) break;
m = num; num;

LCP

定义

suff(i) 表示以 i 开头的后缀。

height[i] 表示排名为 i 与排名为 i1 的后缀字符串的前缀。

h[i] 表示位置为 i 与它的排名1 的后缀字符串的前缀。

形式化的:

height[i]=lcp(suff(sa[i]),suff(sa[i1]))h[i]=height[rk[i]],height[i]=h[sa[i]]

有这样的好性质:

h[i]h[i1]1lcp(suff(i),suff(j))=minx=rk[i]+1rk[j]lcp(suff(sa[x]),suff(sa[x1]))=minx=rk[i]+1rk[j]height[x]

所以要算 lcp 直接用一个 RMQ 就可以了。

求 h 数组

这里很好理解。

for(int i = 1; i <= n; ++i){
		h[i] = h[i - 1] - 1;
		if(h[i] < 0) h[i] = 0;
		while(a[sa[rk[i]] + h[i]] == a[sa[rk[i] - 1] + h[i]] ) ++h[i];
	}
posted @   He_Zi  阅读(19)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示