【详解】树上后缀排序
P5353 树上后缀排序
后缀数组
因为觉得题解区内的一些后缀数组做法的解释并没有解释到点子上,遂写此题解。
思路
注意这题字符串是从当前节点向上,编号却是从根向下……
我们称一个字符串的净大小为这个字符串的值(不考虑编号)的大小,实际大小为按照题目所给判断方式的大小。
倍增构造SA,考虑需要顺序按照哪些关键字排序:(越前面的关键字优先级越高)
- 当前字符串的净大小。
- 祖先字符串的净大小。
- 祖先字符串的编号大小。
- (当前字符串的净大小)
当前字符串的编号大小。
可以将2,3合并,将4前面增加一个1(因为如果比较到了第4关键字,第1关键字必然相等,可以随意添加),如下:
- 当前字符串的净大小。
- 祖先字符串的实际大小(实际为(净大小,编号)的二元组)。
- 当前字符串的实际大小(同上)。
这样便不需要额外维护字符串编号的大小了(而且排序的时候也少一个关键字)。
实现
在排序时:需要保证第一个数组是第一关键字,第二个数组是第二关键字的逆。
预处理
以字符大小为第一关键字,以当前节点编号为第二关键字,排序即可。
倍增
考虑前一轮已经完成对字符串前1<<k
个字符的排序,设顺序为sa
,净大小(不考虑编号)为rk
(可两两相同),实际大小(考虑编号)为rkk
(两两不同)。
那么,可以顺序按照如下的关键字来排序,得到1<<(k+1)
的答案:
- 首先比较当前字符串净大小的
rk
: - 祖先的实际大小
rk2
(由rkk
得到)。 - 当前字符串的
sa
(实际为rkk[cur]
的逆)。
排序时可以先合并后两个关键字,再将得到的与第一关键字合并。