Longest Palindromic Subsequence 题解
题目来源:https://leetcode.com/problems/longest-palindromic-subsequence/description/
Description
Given a string s, find the longest palindromic subsequence's length in s. You may assume that the maximum length of s is 1000.
Example 1:
Input:
"bbbab"
Output:
4
One possible longest palindromic subsequence is "bbbb".
Example 2:
Input:
"cbbd"
Output:
2
Solution
class Solution {
public:
int longestPalindromeSubseq(string str) {
int n = str.length(), high, low;
vector<vector<int>> dp(n, vector<int>(n, 0));
for (high = 0; high < n; high++) {
dp[high][high] = 1;
for (low = high - 1; low >= 0; low--) {
if (str[low] != str[high])
dp[high][low] = max(dp[high][low + 1], dp[high - 1][low]);
else
dp[high][low] = dp[high - 1][low + 1] + 2;
}
}
return dp[n - 1][0];
}
};
解题描述
这道题是经典的求字符串中最长回文子序列的长度的问题。采用的办法是动态规划:
- 对一个字符串,如果头尾的字符不同,该字符串的最长回文子序列的长度就是去掉头字符的的子串的最长回文子序列的长度和去掉尾字符的的子串的最长回文子序列的长度二者中较大值
- 如果头尾的字符相同,该字符串的最长回文子序列的长度就是去掉头尾字符的的子串的最长回文子序列的长度+2
上面的解法中,按理论来说dp
第一个下标可以是low
,但是如果将high
和low
对调的话较为符合局部性原理,数据可以更多地在cache中读取,减少了访问内存的次数,因此速度较快(实际在LeetCode上的测试结果也是如此)。
拓展
如果问题改成求一个字符串的回文子序列数目(或者将一个字符串去掉某些字符以获得一个回文字符串的方案数)的话,同样可以使用动态规划的办法,状态转移上面也是针对头尾字符是否相同进行区分:
- 如果头尾字符不同,字符串的回文子序列数目 = 去掉头字符后字符串的回文子序列数目 + 去掉尾字符后字符串的回文子序列数目 - 去掉头尾字符后字符串的回文子序列数目
- 如果头尾字符相同,字符串的回文子序列数目 = 上一情况的结果 + 去掉头尾字符后字符串的回文子序列数目 + 1 = 去掉头字符后字符串的回文子序列数目 + 去掉尾字符后字符串的回文子序列数目 + 1