算法课第7周第1题——516. Longest Palindromic Subsequence

来源:互联网 发布:华南理工大学软件学院 编辑:程序博客网 时间:2024/06/05 07:38

题目描述:

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
One possible longest palindromic subsequence is "bb".


程序代码:

class Solution {public:int longestPalindromeSubseq(string s) {int strLen = s.size();// 若输入字符串长度为0, 输出回文长度0if (strLen == 0) {return 0;}// 创建一个用于动态规划的向量dp(相当于strLen * strLen大小的二维数组)// dp[left][right]表示[left, right]之间最大的回文串长度vector<int> temp(strLen, 0);vector<vector<int>> dp(strLen, temp);// 外层循环,设len为每次计算用的dp数组的长度,从len为1开始,直到len为strLen,不断循环计算for (int len = 1; len <= strLen; len++) {// 内层循环,dp数组左端为left, dp右端为right = left + len - 1for (int left = 0; left + len - 1 < strLen; left++) {int right = left + len - 1;// 若left == right,说明回文长度为1if (left == right) {dp[left][right] = 1;}// 若left + 1 == right, 则看字符串两端是否相等,相等则回文长度为2,否则为1else if (left + 1 == right) {dp[left][right] = (s[left] == s[right]) ? 2 : 1;}// 其他情况下,根据两端是否相等做不同判断else {// 若两端相等,则回文长度为以下三种情况中的最大值:// 1. 去掉左端后的回文长度 2. 去掉右端后的回文长度 3. 去掉两端后的回文长度+2if (s[left] == s[right]) {int tempMax = max(dp[left + 1][right], dp[left][right - 1]);dp[left][right] = max(tempMax, dp[left + 1][right - 1] + 2);}// 若两端不相等,则回文长度为以下三种情况中的最大值:// 1. 去掉左端后的回文长度 2. 去掉右端后的回文长度 3. 去掉两端后的回文长度else {int tempMax = max(dp[left + 1][right], dp[left][right - 1]);dp[left][right] = max(tempMax, dp[left + 1][right - 1]);}}}}return dp[0][strLen - 1];}};


简要题解:

本题用到了动态规划的算法。

首先理解题意。本题是要求出给定字符串中最长的回文串的长度,根据所给示例可以看出,这个回文串不要求是连续字符组成的字符串。

要使用动态规划的方法,首先需要将大问题化解为小问题。由于本题是求最长回文串(正着反着相同)长度,所以需要考虑一个串两端字符是否相同。因此可以做如下分析:

(1)若某个串左端和右端相同,则这个串中最长回文串的长度可以分解成以下三种情况:1. 去掉左端后的子串的最长回文长度 2. 去掉右端后的子串的最长回文长度 3. 去掉两端后的最长回文长度+2(因为两端相同,算入回文串,所以长度是+2)。如下图所示:


(2)若某个串左端和右端不相同,则这个串中最长回文串的长度可以分解成以下三种情况:1. 去掉左端后的子串的最长回文长度 2. 去掉右端后的子串的最长回文长度 3. 去掉两端后的最长回文长度。如下图所示:


这样我们就将大问题分解成了小问题,不过分解到最后有两种最小问题的情况:

(1)若最后分解到串的左端和右端相同,即长度为1的串,则其最长回文长度就为1。如下图所示:


(2)若最后分解到串的左端 + 1为右端,即长度为2的串,则有两种可能:若左端右端相同,则最长回文长度为2;若左端右端不同,则最长回文长度为1.如下图所示:



这样我们就确定了动态规划的步骤。建立一个二维数组(用向量表示)dp,dp[left][right]表示left和right两端之间的字符串的最长回文长度。从串长度为1开始,直到长度和整个字符串相等,持续循环,计算出各种情况下dp数组的值(即不同的两端情况下串的最长回文长度)。最后只需返回dp[0][strLen-1]即为所求的整个字符串的最长回文长度。

通过本题的求解,我进一步理解了动态规划算法的运用,特别是理解到,动态规划和之前所学的分治算法有一些相似之处(都分解成小问题),也有不同之处(分解出的小问题规模不同),两种算法都有其适合的情况。接下来我还会再练习一些动态规划的题目,加深对其的理解。

0 0
原创粉丝点击