字符串后缀科技

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\)。求和后即为

\[\dfrac{n(n-1)}{2} - \sum\limits_{i=2}^n ht_i \]

PHRASES - Relevant Phrases of Annihilation

拼接,二分答案,对于每个串单独处理最大与最小即可。

P4248 [AHOI2013] 差异

很容易将前一半只与长度相关的式子变形为

\[\text{原式}=(n-1)\sum\limits_{i=1}^n i= \dfrac{(n+1)n(n-1)}{2} \]

那么剩下的部分相当于求 \(\text{Height}\) 所有区间的最小值之和,这就是单调栈板子了。

posted @ 2024-08-28 18:03  Aurora_Borealis  阅读(4)  评论(0编辑  收藏  举报