一个简单题的题解
下面用 \(+\) 表示字符串拼接,\(S[l, r]\) 表示 \(S_l + S_{l + 1} + \ldots + S_r\)。
题意:给定字符串 \(S, T\),接着在 \(S\) 和 \(T\) 中各选一个子串 \(p, q\),使得 \(p + q\) 能被某个串重复两次得到。
假设 \(p = S[l, r], |p| > |q|\),答案串 \(p + q = H + H\)。因为 \(|p| > |q|\),所以 \(H\) 为 \(p\) 的一个前缀。考虑把 \(p\) 分成 \(3\) 段:
划分的条件是 \(H = S[l, b - 1]\) 且 \(S[b, r] = S[l, a]\),这时不难发现 \(q = S[a + 1, b - 1]\)。
于是可以写出朴素的 \(O(n^3)\) 的做法:枚举 \(a, b, r\),这时 \(l = a - (r - b)\),通过计数 \(S[a + 1, b - 1]\) 在 \(T\) 中的出现次数就能求出答案。
考虑优化上述做法,只枚举 \(a, r\),可以发现 \(S[l, a] = S[b, r] \iff b > r - \operatorname{LCS}(a, r)\),其中 \(\operatorname{LCS}(a, r)\) 表示前缀 \(S[1, a]\) 与 \(S[1, r]\) 的最长公共后缀。
当 \(l, b\) 分别从 \(a, r\) 往前移动时,一旦出现某一位 \(S_{l'} \ne S_{b'}\),那么后续的 \(S[l, a]\) 都不等于 \(S[b, r]\),而第一个不同的位就是 \(r - \operatorname{LCS}(a, r)\)。求 \(\operatorname{LCS}\) 可以 \(O(n^2)\) 预处理。
接下来就是求
其中 \(\operatorname{occ}(R)\) 表示 \(R\) 在 \(T\) 中的出现次数。
由于左端点 \(a + 1\) 是固定的,如果能对于任意 \(l, r\) 求出 \(\operatorname{occ}(S[l, r])\),就可以通过前缀和预处理求出答案了。
于是考虑用 SAM,对 \(S\) 和 \(T\) 建一个广义后缀自动机,对于后缀树上的每个节点,预处理子树内有多少个 \(T\) 的前缀。求 \(\operatorname{occ}\) 时,固定 \(r\) 并让 \(l\) 从小往大枚举,枚举过程中维护当前跳到了后缀树上哪个结点,就可以求出所有 \(\operatorname{occ}(S[l, r])\) 了。
对于 \(|p| < |q|\) 的情况,把 \(S, T\) 交换后求一遍 \(|p| > |q|\) 即可;而对于 \(|p| = |q|\),这部分的答案就是 \(\sum_{1 \le l \le r \le n} \operatorname{occ}(S[l, r])\),在上面预处理时就已经求过了。
总时间复杂度 \(O((n + m)^2)\),空间复杂度 \(O(n^2)\),可以通过。

浙公网安备 33010602011771号