后缀平衡树

感觉“后缀平衡树”这个名字起得并不是很好(?),大概是,译者希望表明它和后缀数组等算法的联系,才取的这个名字吧。

后缀平衡树做的事情与后缀数组类似,都是,将一个字符串的所有后缀按字典序进行排列。后缀平衡树的优势在于,它是动态的,可以支持在字符串的最前面插入字符。有些时候我们要做的是在字符串的最后面插入字符,并对其前缀排序,这个东西显然是与后缀排序本质相同的,将字符串倒过来即可。

下面说说后缀平衡树到底在做什么。

考虑如何刻画在字符串开头添加字符的过程。后缀排序或者是一些哈希技巧(e.g.)是可以被理解为,用类似倍增的思想做这件事的。但它们的功能都不够强大。

这里我们考虑在暴力做法的基础上,优化求新添加的字符串的排名的过程。你发现一个字符串的信息太多了,我们必须要按位比较,于是就爆了。于是考虑压缩一个字符串的信息。我们钦定我们已经知道了后面的那些后缀的排名,同时对于新后缀,我们虽然不知道它的排名,却知道它的第一个字符的值。考虑将一个后缀 \(s_{i, n}\) 表示为 \((s_i, \text{rk}_{s_{1, n}})\)。这个东西的信息量是 \(O(1)\) 的,于是我们就能快速地知道当前后缀的排名了。

然而现在产生了一个新的问题:我们需要将所有排名比当前后缀大的后缀的排名加一。那咋办?考虑用一个固定的值表示排名。

这里我们引入替罪羊树。考虑替罪羊树的一个优势:它的树形态不会发生变化(其实是有重构的情况,但我们可以在暴力重构的过程中算所有信息,因此不考虑)。考虑对替罪羊树上的每个节点都赋一个区间 \([l, r]\),这个节点对应的后缀的排名就是 \(\frac{l + r} / 2\),同时树的中序遍历就是排名顺序。因为替罪羊树的树高是 \(O(\log n)\) 的,因此排名信息为 double 即可避免冲突。

P6164 【模板】后缀平衡树

模板题。

考虑刻画子串为后缀的前缀,于是对于一个字符串,用字典序小于它的后缀数量,与字典序小于它的后继的后缀数量做差即可求得它的出现次数。

注意询问的字符串要先翻转。

posted @ 2026-04-09 15:45  zyb_txdy  阅读(20)  评论(0)    收藏  举报