广义SAM 练习题

P6793 SNOI2020 字符串

转化一下题意,即任意排列 \(A,B\),使得以下表达式最小:

\[\sum |A_i|-\operatorname{lcp}(A_i,B_i)=k(n-k+1)-\sum \operatorname{lcp}(A_i,B_i) \]

\(T=\sum\operatorname{lcp}(A_i,B_i)\),即最大化 \(T\)

在 Trie 上考虑,即把 \(A,B\) 所有串扔进 Trie 里,标记结束结点,两个结点的 \(\operatorname{lca}\) 的深度就是这两个路径组成的字符串的 \(\operatorname{lcp}\)

而直接建立字典树的复杂度是 \(O(k(n-k+1))\),不可行。

\(k\) 看着很烦,考虑将 \(k\) 转化一下。

\(s_i\) 为串 \(a\) 的前缀 \(a_{1\sim i}\)\(t_i\) 为串 \(b\) 的前缀 \(b_{1\sim i}\)

\(T=\sum \min(k,\operatorname{lcp}(s_i,t_i))\),即两个前缀的 \(\operatorname{lcp}\)\(k\)\(\min\)。注意 \(i+k-1>n\) 就没贡献了。

建 Trie 看上去不太能优化,考虑 SAM。

将两个串取反,则此时 \(s_i\)\(t_i\) 都是反串后缀。

题目变为最大化最长公共后缀的和。在 parent 树上考虑两个串的最长公共后缀是什么。

显然,某个串的后缀就是它所在状态到根的那一条链。则两个串公共后缀就是两条链的交集。

因为 parent 树上状态的深度越大则其代表的字符串越长,则最长公共后缀就是深度最小的那个结点,即它们的 \(\operatorname{lca}\) 中最长的那一个字符串的长度。

考虑对 \(s\)\(t\) 建出(伪)广义后缀自动机,在某些结点打上颜色不同的标记。则化为一个树上问题:

树上有若干个点,其中一些被染成了黑/白色,求两两匹配的 \(\operatorname{lca}\) 的和最大。

突然发现这是我们 NOIP 前某一场模拟赛 T1 是怎么回事。。。

同一个子树匹配肯定更优,考虑从子节点到根节点不断积累贡献,并把黑白点抵消,这里肯定是能抵消则抵消,剩下一些多余的黑/白点就必须上传到父节点处理贡献了。

标记的条件是,这个字符可以作为一个被拎出来的第一个字符。


其实还有更多更多广义 SAM 和 SAM 的好题的,但我本来目的就是熟悉 SAM 就够了,所以剩下的题后面来做吧。

posted @ 2025-01-03 20:57  _E_M_T  阅读(23)  评论(0)    收藏  举报