字符串后缀科技
SA
定义
- \(sa_i\) 表示字典序从小到大排名为 \(i\) 的后缀的位置
- \(rk_i\) 表示位置为 \(i\) 的后缀的排名
- \(suf_i\) 表示下标为 \(i\) 的后缀
- \(LCP(i,j)\) 表示 \(suf_i\) 和 \(suf_j\) 的最长公共前缀
显然,有 \(sa_{rk_i}=i\)。
后缀排序
考虑只有一个字符的情况。显然该字符排名为 \(1\),进一步,考虑两个字符。显然这个两个字符的串的排名为按第一个字符的排名为第一关键字,第二个字符的排名为第二关键字排序的排名。考虑重复这个倍增的过程,直至所有串的排名均不同,即可得出后缀的排名。普通的 \(sort\) 是 \(O(n \log^2 n)\) 的,由于排名的值域是 \(n\),使用桶排序即可消掉一只 \(\log\)。
在实现时,为了优化常数,可以优化掉不必要的第二关键字排序。首先将没有第二关键字的点加入数组,然后对于 \(1\) 到 \(n\) 的 \(sa_i\),如果其大于 \(w\),那么将 \(sa_i-w\) 加入数组。
同时,我们可以动态记录桶的大小,而不是每次都遍历到 \(n\)。
\(\text{Height}\) 数组
定义 \(ht_i\) 为 \(suf_{sa(i)}\) 与 \(suf_{sa(i-1)}\) 的最长公共前缀长度 \(|LCP(sa_i,sa_{i-1})|\)。特别地, \(ht_1=0\)。
引理:
若存在 \(rk_i < rk_j < rk_k\),则一定有
\(|LCP(i,k)| \leq |LCP(i,j)|\)
\(|LCP(i,k)| \leq |LCP(j,k)|\)
显然排名越近,越可能相似。
对于 \(ht_i\),令 \(p=sa_i+1\),\(q=sa_{i-1}+1\),那么若 \(ht_i >0\),则有 \(|LCP(p,q)|=ht_i-1\)。同时也有 \(rk_q <rk_p\)。
我们设排名为 \(rk_p-1\) 的位置为 \(r\),那么一定有 \(rk_q \leq rk_r\),那么 \(rk_q \leq rk_r < rk_p\)。
根据引理可知 \(|LCP(rk_q,rk_p)| \leq |LCP(rk_q,rk_p)|\)
即 \(ht_i-1 \leq ht_{rk(p)}\)
变形可得 \(ht_{rk[sa[i]]} -1 \leq ht_{rk[sa[i]+1]}\)
设 \(u=sa_i\)
则 \(ht_{rk[u]} -1 \leq ht_{rk[u+1]}\)
这样,我们可以依次求出 \(rk_i\) 的 \(\text{height}\) 值,由于有上面的性质,每次可以直接继承 \(rk_{i-1}\) 的 \(\text{Height}\),减一之后暴力匹配,这样的复杂度是线性的,这是因为指针只会减一 \(n\) 次,而剩余的操作只会把指针右移。
应用
任意子串 \(\text{LCP}\) 长度
$LCP(i,j) = \min\limits_{k=rk_i+1}^{rk_j} ht_k $
运用此性质,可以有通用套路:\(\text{Height}\) 分段,下面题目会有讲解。
练习题
P2743 [USACO5.1] 乐曲主题Musical Themes
最长不重复多次出现子串。\(\text{Height}\) 分段经典题目。
首先求出原串的 \(\text{Height}\),然后二分答案,check 时可以将 \(ht\) 数组分为若干个极大的 \([l,r]\) 区间,使得区间都满足 $ i \in [l+1,r] , ht_i \geq mid$。这样的话,对于每一个区间内所有后缀的 \(\text{LCP}\) 都是大于等于 \(mid\) 的,这样就只需要对于每一段求出 \(sa\) 数组的 \(\max\) 和 \(\min\),若两者相减大于等于 \(mid\),则不相交。
UVA11107 Life Forms
将所有串用分隔符隔开后拼到一起。
同理也可以二分,然后分段。多处理一个 \(bel\) 数组,表示排名 \(i\) 的后缀来自的原串编号,分段后处理一个桶即可。
SUBST1 - New Distinct Substrings
首先可知子串就是后缀的前缀。而两个后缀重复的前缀的个数,即为重复子串的个数,即为 \(ht_i\)。对于 \(sa_i\),其贡献为 \(n-sa_i+1-ht_i\)。求和后即为
PHRASES - Relevant Phrases of Annihilation
拼接,二分答案,对于每个串单独处理最大与最小即可。
P4248 [AHOI2013] 差异
很容易将前一半只与长度相关的式子变形为
那么剩下的部分相当于求 \(\text{Height}\) 所有区间的最小值之和,这就是单调栈板子了。
本文来自博客园,作者:Aurora_Borealis,转载请注明原文链接:https://www.cnblogs.com/Aurora-Borealis-Not-Found/p/18385145