动态规划&记忆化搜索

基础模板

最长上升子序列1

模板题,定义 \(dp_i\) 表示以 \(i\) 结尾的 LIS 长度。
code

最长上升子序列2

数据范围变大了。思路后面补。
code

最长上升子序列3

叫你输出序列。

定义 \(pre_i\) 表示让 \(dp_i\) 最大的 上一个数的编号。

判断里面加一句:\(pre[i]=j\)

code

最长公共子序列1

\(dp[i][j]\) 表示字符串 \(x\)\(i\) 个和字符串 \(y\)\(j\) 个的 LCS。

  • \(x[i]=y[j]\)\(dp[i][j]=dp[i-1][j-1]+1\).
  • 否则:\(dp[i][j]=\max (dp[i-1][j],dp[i][j-1])\).

最长公共子序列2

题目链接

关于为什么可以转化成 LIS 问题,这里提供一个解释。

A:3 2 1 4 5
B:1 2 3 4 5

我们不妨给它们重新标个号:把 \(3\) 标成a,把 \(2\) 标成b,把 \(1\) 标成c……于是变成:

A: a b c d e
B: c b a d e

这样标号之后,LCS 长度显然不会改变。但是出现了一个性质:

  • 两个序列的子序列,一定是 A 的子序列。而 A 本身就是单调递增的。因此这个子序列是单调递增的。

换句话说,只要这个子序列在B中单调递增,它就是A的子序列。

哪个最长呢?当然是B的 LIS 最长。

所以只需要 \(O(n\log n)\) 求一个 LIS 即可。(具体见最长上升子序列2

code

posted @ 2021-11-15 22:02  Otue  阅读(65)  评论(0编辑  收藏  举报