力扣5. 最长回文子串(动态规划)
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例 1:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
示例 2:
输入: "cbbd"
输出: "bb"
动态规划
空间换时间
1、确定状态
1.1、最后一步
以i为起始位置,j为终止位置的字符串是回文子串
1.2、子问题
以i+1为起始位置,j-1为终止位置的字符串是回文子串
因此,状态为:
2、转移方程
3、初始条件和边界情况
4、计算顺序
二维表格
因为当前值取决于左下角的值,因此是先列后行。
复杂度分析
- 时间复杂度:O(n^2),其中 n 是字符串的长度。动态规划的状态总数为 O(n^2),对于每个状态,我们需要转移的时间为 O(1)。
- 空间复杂度:O(n^2),即存储动态规划状态需要的空间
//
// main.cpp
// longestPalindrome
//
// Created by MXQ on 2020/10/16.
//
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Solution {
public:
string longestPalindrome(string s) {
int n=s.size();
int sbegin=0;
int send=0;
vector<vector<bool>> f(n,vector<bool>(n));
//初始化
for (int i=0; i<n; i++) {
f[i][i]=true;
f[i][i+1]=(s[i]==s[i+1]);
if (f[i][i+1]) {
sbegin=i;
send=i+1;
}
}
//先列后行,因为需要看左下角的值
for (int j=0; j<n; j++) {
for(int i=0;i<j-1;i++){
{
f[i][j]=(s[i]==s[j] && f[i+1][j-1]);
if (f[i][j] && (j-i)>(send-sbegin)) {
sbegin=i;
send=j;
}
}
}
}
return s.substr(sbegin,send-sbegin+1);
}
};
int main(int argc, const char * argv[]) {
// insert code here...
string str="abssbd";
Solution s;
auto result=s.longestPalindrome(str);
std::cout <<result<<endl;
std::cout << "Hello, World!\n";
return 0;
}
class Solution {
public:
string longestPalindrome(string s) {
int n = s.size();
vector<vector<int>> dp(n, vector<int>(n));
string ans;
for (int l = 0; l < n; ++l) {
for (int i = 0; i + l < n; ++i) {
int j = i + l;
if (l == 0) {
dp[i][j] = 1;
} else if (l == 1) {
dp[i][j] = (s[i] == s[j]);
} else {
dp[i][j] = (s[i] == s[j] && dp[i + 1][j - 1]);
}
if (dp[i][j] && l + 1 > ans.size()) {
ans = s.substr(i, l + 1);
}
}
}
return ans;
}
};
暴力法
时间复杂度:O(n^3),超时