题目链接leetcode-cn.com/problems/lo…
给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:
输入: s = "babad"
输出: "bab"
解释: "aba" 同样是符合题意的答案。
示例 2:
输入: s = "cbbd"
输出: "bb"
示例 3:
输入: s = "a"
输出: "a"
示例 4:
输入: s = "ac"
输出: "a"
提示:
1 <= s.length <= 1000s仅由数字和英文字母(大写和/或小写)组成
解法:动态规划。
一:确定状态
根据问题寻找 s 中最长的回文子串。我们假设字符串x为回文串,那么我们在x前后各增加同一个字符,得到的新串肯定为一个回文串。 由此假设可知 (1)最后一步为:在x前后各增加同一个字符,得到最长的回文子串。
(2)子问题:用长为L得回文串str,在其前后各增加同一个字符,得到长为L+2的新回文串
二:确定转移方程 我们用P(i,j) 表示字符串 s 的第 i 到 j个字母组成的串(下文表示成 s[i:j]s[i:j])是否为回文串。
那么P(i,j)我们就可以根据P(i+1,j-1)以及(s[i]==s[j])的情况来判断它是否为回文串,很显然 当P(i+1,j-1)为回文串并且s[i]==s[j]这两个字符相等就符合要求。
如果P(i,j)为true且长度大于已发现得长度,就更新最长的回文子串。(附:j-i+1=L)
三:边界初始化
当j-i<3时,d[i][j]=true。(例如"aba","aa","a")
string longestPalindrome(string s){
int len = s.size();
vector< vector<int> > dp(len, vector<int>(len));
int start = 0, maxL = 1;
for (int L = 1; L <=len; L++)
{
for (int i = 0; i < len; i++)
{
int j = i + L - 1;
if (j>=len)
{
break;
}
if (s[i]!=s[j])
{
dp[i][j] = false;
}
else
{
if (j-i<3)
{
dp[i][j] = true;
}
else
{
dp[i][j] = dp[i+1][j-1];
}
}
if (dp[i][j]&&L>maxL)
{
start = i;
maxL = L;
}
}
}
return s.substr(start, maxL);
}