个人主页:元清加油_【C++】,【C语言】,【数据结构与算法】-CSDN博客
个人专栏
力扣递归题
【C++】
http://t.csdnimg.cn/6AbpV
数据结构
前言:这个专栏主要讲述动态规划算法,所以下面题目主要也是这些算法做的
我讲述题目会把讲解部分分为3个部分:
1、题目解析
2、算法原理思路讲解
3、代码实现
最长回文子串
题目链接:最长回文子串
题目
给你一个字符串 s
,找到 s
中最长的回文
子串
。
如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。
示例 1:
输入:s = "babad" 输出:"bab" 解释:"aba" 同样是符合题意的答案。
示例 2:
输入:s = "cbbd" 输出:"bb"
提示:
1 <= s.length <= 1000
s
仅由数字和英文字母组成
解法
算法原理与解析
我们这题使用动态规划,我们做这类题目可以分为以下五个步骤
- 状态显示
- 状态转移方程
- 初始化(防止填表时不越界)
- 填表顺序
- 返回值
- 状态显示
为了能表示出来所有的子串,我们可以创建⼀个 n*n 的二维 dp 表,只⽤到「上三⻆部分」即可。 其中, dp[ i ][ j ] 表示 : s 字符串 [i, j] 的⼦串,是否是回文串。
- 状态转移方程
对于回文串,我们⼀般分析⼀个「区间两头」的元素:
- 当 s[i] != s[j] 的时候:不可能是回⽂串, dp[i][j] = 0 ;
-
当 s[i] == s[j] 的时候:根据长度分两种情况讨论
-
长度小于等于为 2 ,也就是 i + 1 == j 或 i == j:此时也⼀定是回⽂串, dp[i][j] = true
-
长度大于 2 ,此时要去看看 [i + 1, j - 1] 区间的⼦串是否回⽂: dp[i][j] = dp[i + 1][j - 1]
-
- 初始化(防止填表时不越界)
无需初始化
- 填表顺序
根据「状态转移⽅程」,我们需要「从下往上」填写每⼀⾏,每⼀⾏的顺序⽆所谓。
代码实现
class Solution {
public:
string longestPalindrome(string s)
{
int n = s.size();
vector<vector<bool> > dp(n, vector<bool>(n));
int len = 1;
int begin = 0; // 标记最长子串的起始位置和⻓度
// 填表,从下往上填
for (int i = n - 1; i >= 0; i--)
{
for (int j = i; j < n; j++)
{
if (s[i] == s[j])
{
dp[i][j] = i + 1 < j ? dp[i + 1][j - 1] : true;
}
if (dp[i][j] && j - i + 1 > len) // 找出子串中最⻓的回⽂⼦串
{
len = j - i + 1;
begin = i;
}
}
}
return s.substr(begin, len);
}
};