最长回文子序列 - LeetCode (中国)
题目描述:
给定一个字符串s,找到其中最长的回文子序列。可以假设s的最大长度为1000。
示例 1:
输入:
"bbbab"
输出:
4
一个可能的最长回文子序列为 "bbbb"。
示例 2:
输入:
"cbbd"
输出:
2
一个可能的最长回文子序列为 "bb"。
思路:
经典的动态规划问题
记:
dp[i][j] := 子串 s[i..j] 的最长回文子序列的大小
初始化:
dp[i][j] = 1 i=j //s[i..i]为单个字母
= 0 other
递推公式:
dp[i][j] = dp[i+1][j-1] + 2 s[i]==s[j]
= max(dp[i+1][j], dp[i][j-1]) other
1.如果str的最后一个元素和第一个元素是相同的,则有:lps(0,n-1)=lps(1,n-2)+2;例如字符串序列“AABACACBA”,第一个元素和最后一个元素相同,其中lps(1,n-2)表示红色部分的最长回文子序列的长度;
2.如果str的最后一个元素和第一个元素是不相同的,则有:lps(0,n-1)=max(lps(1,n-1),lps(0,n-2));例如字符串序列“ABACACB”,其中lps(1,n-1)表示去掉第一元素的子序列,lps(0,n-2)表示去掉最后一个元素的子序列。
如果 `i+1=j` 且 `s[i]=s[j]`时,`dp[i][j] = dp[i+1][j-1] + 2` 依然成立,
因为 `i != j` 时,有 `dp[i][j] = 0`
注意,如果按照上面的 dp 定义,返回值应该是 dp[1][n] 而不是 dp[n][n]
明白状态转移之间的关系是理解所有动态规划问题的关键,也是难点
s[i]==s[j] 时,s[i..j] 的上一个状态应该是 s[i+1..j-1],两头收缩,而不是 s[i+1..j+1] 或者其他,明白这一点是理解本题的关键
s[i]!=s[j] 时,s[i..j] 的上一个状态应该是 s[i+1..j] 或 s[i..j-1]
暂不考虑 DP 的优化
状态更新的顺序也是一个注意点:
正确示例:
//abcdef a-a-1 ... c-c-1结束位置控制全局
for (int j = 1; j < n; j++) // 子串结束位置
for (int i = j-1; i >=0; i--) { // 子串开始位置
//abcdef f-f+1 ... d-d+1开始位置控制全局
for (int i = n-1; i >= 0; i--) // 子串开始位置(>=0)
for (int j = i + 1; j < n; j++) { // 子串结束位置(<n)
for (int j = 1; j < n; j++) //子串长度(s[i..i+j])
for (int i = 0; j + i < n; i++){ //子串开始位置(开始到结束闭区间<n)
错误示例:
for (int j = 1; j < n; j++) // 子串结束位置
for (int i = 0; i < j; i++) { // 子串起始位置
// 但是该顺序在 "./最长回文子串.hpp" 中是正确的
注意:
因为 DP 的定义为了便于理解,下标常从 1 开始,这与一般容器的下标不同,所以
应该使用编码时应该使用 `s[i-1]==s[j-1]` 而不是 `s[i]==s[j]`
**当然也可以在编码时将 DP 的下标也调整至从 0 开始**
最后,这题只返回了最长回文子序列的长度,一般面试题中也只是要求返回长度即可。
但是如果你也想知道最长回文子序列具体是啥,这可以额外添加一个变量记录最长回文子序列是哪些字符,例如维护一个键为 lps[j][i + j],值为 String 的 map。
1 |
|
最长回文子串 - LeetCode (中国)
问题描述:
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为1000。
示例 1:
输入: "babad"
输出: "bab"
注意: "aba"也是一个有效答案。
示例 2:
输入: "cbbd"
输出: "bb"
思路:
动态规划
如果只是求最长回文子串的长度,其递推公式与 "最长回文子序列" 完全相同
这里需要给出具体的子串,需要重新定义 dp
定义:
dp[i][j] := 子串 s[i..j] 是否是回文子串
初始化
dp[i][j] = true i=j
= false other
递推公式:
dp[i][j] = s[i]==s[j] j-i=1
= s[i]==s[j]&&dp[i+1][j-1] j-i>1
本题除了动态规划的另一个难点是如何保存其中一个子串
1 |
|
刚开始的想法是直接DFS,但会超时,也记录一下吧
1 |
|