给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例 1:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
示例 2:
输入: "cbbd"
输出: "bb"
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-palindromic-substring
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
方法一:动态规划
定义:
d
p
(
i
,
j
)
dp(i,j)
dp(i,j)表示字符串
i
:
j
i:j
i:j是否是一个回文串,对于每一个字符也就是当
i
=
=
j
i==j
i==j的时候,
d
p
[
i
]
[
i
]
=
t
r
u
e
dp[i][i]=true
dp[i][i]=true,同时我们每次去判断
s
[
i
]
s[i]
s[i]是否等于
s
[
j
]
s[j]
s[j],如果不相等,说明
s
[
i
:
j
]
s[i:j]
s[i:j]一定是不是回文串。如果相等的话,如果子串的长度不大于3,那么这个字符串也一定是回文串,如果大于3,则需要判断字符串
s
[
i
+
1
:
j
−
1
]
s[i+1:j-1]
s[i+1:j−1]是不是回文串,如果是则
s
[
i
]
[
j
]
s[i][j]
s[i][j]也是。同时维护两个变量
s
t
a
r
t
start
start和
m
a
x
l
e
n
maxlen
maxlen用于记录当前的最大的回文串长度和它对应的首字符起始下标。
需要注意的是: 由于我们需要通过
s
[
i
+
1
,
j
−
1
]
s[i+1, j-1]
s[i+1,j−1],来计算
s
[
i
,
j
]
s[i,j]
s[i,j],因为
i
<
i
+
1
i<i+1
i<i+1,所以我们要先算出
s
[
i
+
1
,
j
−
1
]
s[i+1, j-1]
s[i+1,j−1],也就是要把
i
i
i从大到小遍历。
代码
class Solution {
public:
string longestPalindrome(string s) {
int n = s.size();
if(n==0||n==1) return s;
if(n==2){
if(s[0]==s[1]) return s;
else return s.substr(0, 1);
}
vector<vector<bool>> dp(n, vector<bool>(n, false));
int max_len = INT_MIN;
int start = 0;
for(int i=n-1; i>=0; --i)
{
for(int j=i; j<n; ++j)
{
if(i==j)
{
dp[i][j] = true;
continue;
}
if(s[i]!=s[j])
{
dp[i][j] = false;
}
else
{
if(j-i<3)
{
dp[i][j] = true;
if(dp[i][j] && max_len<j-i+1)
{
start = i;
max_len = j-i+1;
}
}else{
dp[i][j] = dp[i+1][j-1];
if(dp[i][j] && max_len<j-i+1)
{
start = i;
max_len = j-i+1;
}
}
}
}
}
if(max_len==INT_MIN) {
return s.substr(0, 1);
}
return s.substr(start, max_len);
}
};