序列dp

序列dp

最长不下降子序列

我们都会 \(O(n^2)\) 的做法,这里讲的是 \(O(n\ log\ n)\) 的做法。

依旧是求 \(f(i)\) 表示以 \(A_i\) 为结尾的最长不下降子序列的长度。

但我们不再是通过枚举去找到一个最优的 \(A_j \le A_i\),而是维护一些信息直接 \(O(1)\) 判断以 \(A_i\) 为结尾的最长不下降子序列能否为 \(l\)

这里利用了一点贪心的思想,维护一个数组 \(d\)\(d_l\) 表示考虑 \(1\)\(i - 1\) 时,所以长度为 \(k\) 的不下降子序列末尾元素的值最小为多少。

\(A_i \ge d_{l-1}\),则以 \(A_i\) 为结尾的最长不下降子序列长度至少为 \(l + 1\)

不难理解 \(d\) 数组满足 \(d_i \le d_{i + 1}\)

所以可以通过二分找到最大的满足 \(A_i \ge d_{l - 1}\)\(l\),即为 \(f(i)\)

时间复杂度 \(O(n\ log\ n)\)

例题

最长公共子序列

我们都会 \(O(nm)\) 的做法。但特殊的情况下,可以做到 \(O(n\ log\ n)\)

那就是两个序列的元素在对面具有唯一对应的元素。

一个简单的例子就是求两个排列的最长公共子序列。

\(3, 1, 4, 2, 5\)\(1, 4, 3, 2, 5\) 的最长公共子序列,等价于求 \(1, 2, 3, 4, 5\)\(2, 3, 1, 4, 5\) 的最长公共子序列,而后者等价于求 \(2, 3, 1, 4, 5\) 的最长上升子序列。

例题

题面:

给定两个长度分别为 \(n, m\) 且仅由小写字母构成的字符串 \(A\)\(B\)

\(A\)\(B\) 的最长公共子序列。

\(n \le 10^6\)\(m \le 10^3\)

分析:

显然 \(O(nm)\) 无法通过,而且也没有前面提到的性质。怎么办呢?

两个序列的长度很不对称,这一点值得关注。

这时候就需要用到之前提到的技巧,将 dp 的值和状态进行交换。

显然最终答案不会超过较短的序列的长度,也就是不超过 \(m\)

而 LCS 满足一定的单调性,即 \(A[1, i]\)\(B[1, j]\) 的最长公共子序列长度一定不小于 \(A[1, k]\)\(B[1, j]\) 的最长公共子序列长度。

故设状态 \(f(i, j)\) 为:\(A\)\(B\)\(i\) 位的最长公共子序列长度为 \(j\) 的前缀最短是多少(即朴素算法的答案与第一维状态对调)。

预处理 \(A\) 的每一位的下一个 \(a, b, ···, z\) 的出现位置即可 \(O(1)\) 转移。

复杂度 \(O(m^2 + 26n)\),可以通过本题。

RaucousRockers演唱组

题目

\(g(i, j, k)\) 表示前 \(i\) 首歌,用 \(j\) 张唱片加 \(k\) 分钟,最多可包含的歌曲数。

\(k \ge l_i\) 时:

\[g(i, j, k) = max\{g(i - 1, j, k - l_i), g(i - 1, j, k)\} \]

\(k < l_i\) 时:

\(g(i, j, k) = max\{g(i - 1, j - 1, t - l_i), g(i - 1, j, k)\}\)

时间复杂度 \(O(nmt)\)

还可以再优化一下吗?

\(g(i, j) = (a, b)\) 表示前 \(i\) 首歌曲中选 \(j\) 首最少需要:\(a\) 张唱片+\(b\) 分钟。

\[g(i, j) = min(g(i - 1, j), g(i - 1, j - 1) + l_i) \]

其中 \((a, b) + l_i = (a’, b’)\) 定义为:

  • \(b + l_i \le t\) 时:\(a' = a, b' = b + l_i\)
  • \(b + l_i > t\) 时:\(a' = a + 1, b' = l_i\)

题目所求的是:\(max(k | g(n, k) \le (m - 1, t))\)

时间复杂度 \(O(n^2)\)

posted @ 2025-09-07 18:38  FurinaQWQ  阅读(11)  评论(0)    收藏  举报