[ABC257G] Prefix Concatenation Solution

更好的阅读体验戳此进入

题面

给定仅存在小写英文字母的字符串 S,T。你需要将 T 分割成 kS 的前缀(或着说用 S 的若干个前缀组成 T),最小化 k,输出最小值。若 k 不存在输出 -1

Solution

首先 O(n2) 的 DP 显然,我们记 S(i,j),T(i,j) 为对应字符串 [i,j] 的子串,令 dp(i) 表示考虑 T(1,i) 的最小 k。易得转移:

dp(i)=minj<iS(1,ij)=T(j+1,i)dp(j)+1

不难发现这个 1D1D 的 DP 是 O(n2) 的无法通过,考虑优化。

首先有一个思路,已知 dp(i) 单调不降,证明显然,考虑若 dp(i)>dp(i+1),那么在 dp(i+1) 的方案中将最后一部分去掉第 i+1 个一定可以变为 dp(i)k 不劣,得证。

然后根据这个思路我们每次转移只需要找到最小的合法 j 转移即可,可以通过 KMP 中的 next 数组维护。

具体地,不难发现我们这个东西求的可以转化为求 border,具体地,我们将 S 后追加一个占位符,然后再连接上 T,记 P = S + '#' + T,这样我们对 P 跑一遍 KMP 的建立 next 数组过程,不难发现对于转移 i 时需要的 j,即为 inxt(lenS+1+i),这里的 +1 即为我们添加的占位符 #

最终 DP 优化为 1D0D,复杂度 O(n),可以通过。

同时还有一种方法,发现修改状态为后缀可以支持逆序转移,于是转移变为:

dp(i)=minj>iS(1,ji)=T(i,j1)dp(j)+1

此时发现每次可以转移的 j 是连续的,对应 ST(i,lenT) 的 LCP,于是可以通过哈希 + 二分处理每次转移的 LCP 长度,然后线段树优化 DP 即可,最终复杂度 O(nlogn),劣于正向转移但也可以通过,且思路更直观,仅代码实现略长。

Code

UPD

update-2022_12_09 初稿