[Leetcode] Longest Palindromic Subsequence

时间:2023-03-09 17:44:23
[Leetcode] Longest Palindromic Subsequence

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,但是如果将highlow对调的话较为符合局部性原理,数据可以更多地在cache中读取,减少了访问内存的次数,因此速度较快(实际在LeetCode上的测试结果也是如此)。

拓展

如果问题改成求一个字符串的回文子序列数目(或者将一个字符串去掉某些字符以获得一个回文字符串的方案数)的话,同样可以使用动态规划的办法,状态转移上面也是针对头尾字符是否相同进行区分:

  • 如果头尾字符不同,字符串的回文子序列数目 = 去掉头字符后字符串的回文子序列数目 + 去掉尾字符后字符串的回文子序列数目 - 去掉头尾字符后字符串的回文子序列数目
  • 如果头尾字符相同,字符串的回文子序列数目 = 上一情况的结果 + 去掉头尾字符后字符串的回文子序列数目 + 1 = 去掉头字符后字符串的回文子序列数目 + 去掉尾字符后字符串的回文子序列数目 + 1