Loading

重生之我在子串问题上dp——CF700E Cool Slogans 题解

重生之我在子串问题上dp——CF700E Cool Slogans 题解

首先可以分析出 \(s_{i-1}\) 一定是 \(s_i\) 的 border。考虑可以把首尾多余的位置删掉变成 border,这样更优。问题变成了求所有字串 border 链的最大值,直接KMP是 \(\mathcal O(n^2)\) 的。

考虑dp。设 \(f_i\) 表示以位置 \(i\) 开头的字符串中最长的 border 链长,\(len_i\) 表示取到 \(f_i\) 的最短子串长度。考虑一组转移 \(j\to i\) 的条件,发现为 \(j>i\land \text{LCP}(i,j)\ge len_j\),这由 border 的定义可以导来。

但是,会不会我们可以适当减少 \(f_j\),使得 \(len_i\) 同步减少,以便实现 \(j\to i\) 的成功转移呢?设 \(j\) 是从 \(k\) 转移而来,我们就可以将 \(len_j\) 减小为 \(len_k\)。这样一来,如果 \(j\to i\) 可以转移,那么 \(k\to i\) 的转移也是可以的。所以不用担心这个问题。

考虑如何优化转移。首先从后往前扫描线,可以发现满足条件 \(\text{LCP}(i,j)\ge len_j\)\(i\) 在 sa 上形如连续的一段,而我们可以通过二分将这个区间求出来然后区间取 \(max\),单点求值即可。

考虑如何求出 \(len_i\)。可以发现若最终转移为 \(j\to i\) 则应该有 \(len_i=j-i+len_j\)。但此时有一个问题,如果是 \(len_j\) 将为 \(len_k\) 后产生的 \(j\to i\) 的转移,就有 \(j-i+len_k<k-i+len_k\),此时 \(j\) 的缩小就不能忽略了,怎么办?

假设 \(len_j\) 缩短至 \(len_j'\) 后产生转移 \(j\to i\)\(len_k\) 缩短至 \(len_k'\) 后产生转移 \(k\to i\),一定有\(\text{LCP}(i,j)\ge len'_j,\text{LCP}(i,k)\ge len_k'\),于是得出 \(\text{LCP}(j,k)\ge \min(len_j',len_k')\)。根据定义,设缩短后 \(j,k\) 的值为 \(f_j',f_k'\) 则有 \(f_j'=f_k'=res\),由于以 \(j,k\) 开头的前 \(\min(len_j',len_k')\) 个字符已经可以产生 \(res\) 的贡献,根据 \(len\) 最小的定义,有 \(len_j'=len_k'\)。于是就证明了所有以相同 \(f\) 值转移到 \(i\)\(j\),其缩短后的 \(len'_j\) 都相同,那么我们可以直接取 \(len_k=len'_k\)\(len_k\) 值(即不用缩短的那个)。

于是只需要在得到 \(f_i\) 同时得到 \(len'_j\),再在 SA 上找到满足 \(\text{LCP}(i,j)\ge len'_j\) 的区间 \([L,R]\),设这个区间中的最小可转移下标为 \(p\) (即 \(p>i\) 的最小的 \(p\)),有 \(len_i=p-i+len_j'\)

于是便解决了此题,时间复杂度 \(\mathcal O(n\log n)\),空间复杂度 \(\mathcal O(n)\)

posted @ 2025-05-30 15:45  lupengheyyds  阅读(24)  评论(0)    收藏  举报