5. 最长回文子串
题目描述
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例 1:
输入: “babad”
输出: “bab”
注意: “aba” 也是一个有效答案。
示例 2:
输入: “cbbd”
输出: “bb”
解决思路
解决方法1:反转法
反转字符串S,获得反转后的字符串S1,获取反转后的字符串S1与S的最大公有字符串。此时最大公有字符串不一定是最长回文子串。对子串进行判断,如果不是回文子串,则继续判断下一个回文子串。
该方法比较直接,但是有点繁琐。以下使用动态规划解决。
解决方法2:暴力法(动态规划优化基础)
获取所有子串,对每一个子串判断是否是回文。
时间复杂度:O(n3),空间复杂度O(1)
解决方法3:动态回归1(最长回文子串的子串也为回文子串)
逐步选取回文中心,再从中心逐步增加至当前最长回文子串,与当前最长回文子串比较,如果更长,则作为当前最长回文子串。
递归公式:
P
(
i
,
j
)
=
{
true
S
i
,
.
.
.
,
S
j
,
为
回
文
子
串
false
S
i
,
.
.
.
,
S
j
,
不
为
回
文
子
串
P(i, j)=\left\{\begin{array}{l}{\text { true } \quad S_i,...,S_j,为回文子串} \\ {\text { false } \quad S_i,...,S_j,不为回文子串}\end{array}\right.
P(i,j)={ true Si,...,Sj,为回文子串 false Si,...,Sj,不为回文子串
P
(
i
,
j
)
=
(
P
(
i
+
1
,
j
−
1
)
and
S
i
=
=
S
j
)
P(i, j)=\left(P(i+1, j-1) \text { and } S_{i}==S_{j}\right)
P(i,j)=(P(i+1,j−1) and Si==Sj)
时间复杂度:O(n2),空间复杂度O(1)
class Solution {
public String longestPalindrome(String s) {
if (s == null || s.length() < 1) return "";
int start=0,end=0;
for(int i=0;i<s.length();i++){
int len1=expandAroundCenter(s,i,i);
int len2=expandAroundCenter(s,i,i+1);
int len=Math.max(len1,len2);
if(len>end-start){
start=i-(len-1)/2;
end=i+len/2;
}
}
return s.substring(start,end+1);
}
private int expandAroundCenter(String s,int left,int right){
int L=left;
int R=right;
while(L>=0 && R<s.length() && s.charAt(L)==s.charAt(R)){
L--;
R++;
}
return R-L-1;
}
}
备注:解决动态规划问题只需考虑暴力法以及通过递归公式简化计算的方法,不需要考虑解决方法4的情况。
解决方法4:动态回归2(Manacher 算法)
第一步:字母之间添加‘#’,统一奇数偶数字母的情况。
第二步:顺序遍历字母,利用已计算出的最长子串简化计算。
时间复杂度O(n),空间复杂度O(n)。