问题
Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
Example:
Input: “babad”
Output: “bab”
Note: “aba” is also a valid answer.
Example:
Input: “cbbd”
Output: “bb”
计算最长回文子序列
解析
参考博客1
动态规划求解最长子串的长度
状态初始条件:
dp[i][i]=1(i=0:n−1)
状态转移方程:
dp[i][j]=dp[i+1][j−1]+2(str[i]==str[j])
dp[i][j]=max(dp[i+1][j],dp[i][j−1])if(str[i]!=str[j])
最终返回 dp[0][n−1]
计算dp[i][j]时需要计算dp[i+1][ ]或dp[][j-1],因此i应该从大到小,即递减;j应该从小到大,即递增。
代码:
以下代码为根据该思路写的【一本正经】,且是求最长回文子序列广为流传的代码。看我main中的测试样例pwwkew,最终结果为3,因为dp[3][4] = 1,计算dp[2][5]时,就是dp[3][4]+2 = 3,而非正确结果2。找的多个博客代码运行起来都一样,怎么肥四?有猫病??先放着吧,可能哪儿细节我没看清?
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<unordered_map>
using namespace std;
// 按照转移方程自己打的
class Solution {
public:
int longestPalindrome(string s) {
// matrix[i][j]是s下标从i到j的子串中最长回文子序列的长度
int size = s.size();
vector<vector<int>> dp(size, vector<int>(size, 0));
for (int j = 0; j < size; j++) {
dp[j][j] = 1;
for (int i = j - 1; i >= 0; i--) {
if (s[i] == s[j]) {
dp[i][j] = dp[i + 1][j - 1] + 2;
}
else {
dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);
}
}
}
return dp[0][size - 1];
}
};
// 另外一种博客上做法,总体思路还是一致
int lpsDp(string str, int n)
{
int dp[6][6], tmp;
memset(dp, 0, sizeof(dp));
//字符串长度为1,最长回文子序列的长度就是1
for (int i = 0; i < n; ++i) dp[i][i] = 1;
for (int i = 1; i < n; ++i)
{
tmp = 0;
//考虑所有连续的长度为i+1的子串,str[j....j+i]
for (int j = 0; j + i < n; j++)
{
//如果首尾相同
if (str[j] == str[j + i])
tmp = dp[j + 1][j + i - 1] + 2;
//如果首尾不同
else
tmp = max(dp[j + 1][j + i], dp[j][j + i - 1]);
dp[j][j + i] = tmp;
}
}
return dp[0][n - 1]; //返回字符串str[0...n-1]的最长回文子序列长度
}
int main() {
string str = "pwwkew";
Solution solution;
//int res = solution.longestPalindrome(str);
int res = lpsDp(str, str.size());
cout << res << endl;
system("pause");
return 0;
}
就题论题
解析:
相应AC代码:
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<unordered_map>
using namespace std;
class Solution {
public:
string longestPalindrome(string s) {
// matrix[i][j]是s下标从i到j的子串是否是回文串
int size = s.size();
vector<vector<bool>> dp(size, vector<bool>(size, false));
for (int i = 0; i < size; i++) {
dp[i][i] = true; // 奇数情况初始化
if (i < size - 1) {
dp[i][i + 1] = (s[i] == s[i + 1]); // 偶数情况初始化
}
}
// 转移方程
for (int window = 3; window <= size; window++) {
for (int index = 0; index + window - 1 < size; index++) {
dp[index][index + window - 1] = (s[index] == s[index + window - 1]) && dp[index + 1][index + window - 2];
}
}
// 找出dp[index][index + window - 1]为true,window最大的子序列
int index, window;
for (window = size; window > 0; window--) {
bool flag = false;
for (index = 0; index < size - window + 1; index++) {
if (dp[index][index + window - 1]) {
flag = true;
break;
}
}
if (flag)
break;
}
string substring;
substring.assign(s, index, window);
return substring;
}
};
int main() {
string str = "abcba";
Solution solution;
string res = solution.longestPalindrome(str);
cout << res << endl;
system("pause");
return 0;
}