CF985F Isomorphic Strings 题解

· · 题解

这是一篇确定性做法,个人感觉还是很有启发性的。

不妨定义 s'_i=i-pre_{s_i},其中 pre_{s_i} 表示 s_i 上次出现的位置,若为 s_i 第一次出现则 s'_i=0

不难发现,当 st 同构时,应满足 s'_i=t'_i

考虑怎么求出 s't',它们的共同特点是原串都是 S 中的一个子串。

观察一下,在 S 中对应 s 这段的 S's' 有何不同:会有 O(|\Sigma|) 个在 s 中第一次出现的字符,在 S 中并非第一次出现,除此以外的均满足 S'_i=s'_i

它其实相当于将 S' 分成 O(|\Sigma|) 段,每一段要么是,我当前一定是 0,要么是,我这一段就是原串。

这时候我们再转化一下题意,把 S'_{x_i\sim x_i+len-1}=S'_{y_i\sim y_i+len-1} 换成 \texttt{LCP}(a_{x_i},a_{y_i}) \geq len,其中 a_i 表示 S' 中以 i 结尾的后缀。

不难想到先对 S' 后缀排序,再对 a'_i 进行与 SA 同理的后缀排序,这样子就是转化成了 \min_{k=rnk2_{x_i}+1}^{rnk2_{y_i}} height2_k

现在问题在于如何比较 a'_i 呢?我们是知道 a_i 被分为 O(|\Sigma|) 段的,有若干段是单个数 0,其他段是 S' 的一段子串。

a'_icmph2 其实是同理的,我们暂且以 cmp 为例。

如果不是 $0$,那么两边的这段都一定在原串出现过,我们直接用原串的 $rnk$ 和 $height$ 数组,查询 $\texttt{LCP}$ 是否 $\geq len$,否则直接比较 $rnk$ 大小即可。 如此往复直到遍历到 $n$ 结束,那么长度小的后缀更小。 用 $st$ 表初始化即可做到比较时 $O(1)$ 查询 $\texttt{LCP}$。总复杂度 $O(n|\Sigma| \log n)$,复杂度瓶颈在对 $a'_i$ 排序。 [Submission #331238638 - Codeforces](https://codeforces.com/contest/985/submission/331238638)。看上去有点长其实挺简单的。