5. 最长回文子串
难度中等4264收藏分享切换为英文接收动态反馈
给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:
输入:s = "babad"输出:"bab"解释:"aba" 同样是符合题意的答案。
示例 2:
输入:s = "cbbd"输出:"bb"
示例 3:
输入:s = "a"输出:"a"
示例 4:
输入:s = "ac"输出:"a"
提示:
- 1 <= s.length <= 1000
- s 仅由数字和英文字母(大写和/或小写)组成
学习(代码随想录的思路)
动规五部曲:
- 确定dp数组(dp table)以及下标的含义
布尔类型的dp[i][j]:表示区间范围[i,j] (注意是左闭右闭)的子串是否是回文子串,如果是dp[i][j]为true,否则为false。 - 确定递推公式
- 在确定递推公式时,就要分析如下几种情况。
- 整体上是两种,就是s[i]与s[j]相等,s[i]与s[j]不相等这两种。
- 当s[i]与s[j]不相等,那没啥好说的了,dp[i][j]一定是false。
- 当s[i]与s[j]相等时,这就复杂一些了,有如下三种情况
情况一:下标i 与 j相同,同一个字符例如a,当然是回文子串
情况二:下标i 与 j相差为1,例如aa,也是文子串
情况三:下标:i 与 j相差大于1的时候,例如cabac,此时s[i]与s[j]已经相同了,我们看i到j区间是不是回文子串就看aba是不是回文就可以了,那么aba的区间就是 i+1 与 j-1区间,这个区间是不是回文就看dp[i + 1][j - 1]是否为true。
思路:
“aaaa”
所以一定要从下到上,从左到右遍历,这样保证dp[i + 1][j - 1]都是经过计算
”babad“
上三角与i,j的比较
代码
class Solution {
public:
string longestPalindrome(string s) {
char dp[1000+5][1000+5]={0};
int i,j;
int l,r;
i=j=l=r=0;
for(i=0;i<s.length();i++)
{
dp[i][i]=1;
}
i=s.length()-1;
//所以一定要从下到上,从左到右遍历,这样保证dp[i + 1][j - 1]都是经过计算
//上三角
while(i>=0)
{
j=i;
while(j<s.length())
{
// printf("%d %d\n",i,j);
if((j-i)<=1)
{
if(s[i]==s[j])
{
dp[i][j]=1;
// printf("--%d %d %d\n",i,j,dp[i][j]);
if((r-l)<(j-i))
{
l=i;
r=j;
}
}
}
else{
// printf("==%d %d\n",i,j);
if(s[i]==s[j])
{
// printf("--%d %d\n",i,j);
if(i+1>=s.length()||j-1<0||dp[i+1][j-1]==1)
{
dp[i][j]=1;
// printf("%d-%d,%d-%d\n",l,r,i,j);
if((r-l)<(j-i))
{
l=i;
r=j;
// printf("y\n");
}
}
}
}
j++;
}
i--;
}
// for(i=0;i<s.length();i++)
// {
// for(j=0;j<s.length();j++)
// {
// printf("%d",dp[i][j]);
// }
// printf("\n");
// }
printf("(%d-%d)\n",l,r);
return s.substr(l, r-l+1);
}
};