题目描述
给定一个字符串 s
,找到 s
中最长的回文子串。你可以假设 s
的最大长度为 1000。
示例 1:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
示例 2:
输入: "cbbd"
输出: "bb"
题目分析
对于空串来说,最长的回文子串就是空串,对于非空的字符串来说,最小的最长回文子串是字符串中任意一个字符。
回文子串的长度有奇数有偶数。
对于长度为奇数的回文子串:以当前的字符为回文子串的中心,同时向两边扫描,如果两个字符相同,则继续向后扫描,否则该子串不再是回文子串,停止扫描;
对于长度为偶数的回文子串:以两个相同的字符为回文子串的中心,同时向两边扫描,如果两个字符相同,则继续向后扫描,否则该子串不再是回文子串,停止扫描。
由于题目对时间有一定限制,对于有较多连续相同字符的部分,需要进行优化,可以把连续相同字符的部分看作一个整体,作为回文子串的中心,然后同时向两边扫描,如果两个字符相同,则继续向后扫描,否则该子串不再是回文子串,停止扫描。
代码实现
C++
/*
* @lc app=leetcode.cn id=5 lang=cpp
*
* [5] 最长回文子串
*/
// @lc code=start
class Solution {
public:
string longestPalindrome(string s) {
if(s.size() == 0){
return s;
}
string ans;
ans = s.substr(0,1);
for(int i = 1; i < s.size(); i++){
for(int j = i - 1; j >= 0 && 2*i - j < s.size(); j--){
if(s[j] == s[2*i - j]){
string tmp = s.substr(j,2*i - 2*j + 1);
if(tmp.size() > ans.size()){
ans = tmp;
}
}
else{
break;
}
}
if(s[i - 1] == s[i]){
int end = i + 1;
while(1){
if(end < s.size() && s[end] == s[i]){
end++;
}
else{
break;
}
}
end--;
string tmp = s.substr(i - 1,end - i + 2);
if(tmp.size() > ans.size()){
ans = tmp;
}
for(int j = i - 2; j >= 0 && i - 1 - j + end < s.size(); j--){
if(s[j] == s[i - j - 1 + end]){
string tmp = s.substr(j,i - 2*j + end);
if(tmp.size() > ans.size()){
ans = tmp;
}
}
else{
break;
}
}
i = end;
}
}
return ans;
}
};
// @lc code=end
Java
/*
* @lc app=leetcode.cn id=5 lang=java
*
* [5] 最长回文子串
*/
// @lc code=start
class Solution {
public String longestPalindrome(final String s) {
if (s.length() == 0) {
return s;
}
String ans;
String tmp;
ans = s.substring(0, 1);
for (int i = 1; i < s.length(); i++) {
for (int j = i - 1; j >= 0 && 2 * i - j < s.length(); j--) {
if (s.charAt(j) == s.charAt(2 * i - j)) {
tmp = s.substring(j, 2 * i - j + 1);
if (tmp.length() > ans.length()) {
ans = tmp;
}
} else {
break;
}
}
if (s.charAt(i - 1) == s.charAt(i)) {
int end = i + 1;
while (true) {
if (end < s.length() && s.charAt(end) == s.charAt(i)) {
end++;
} else {
break;
}
}
end--;
tmp = s.substring(i - 1, end + 1);
if (tmp.length() > ans.length()) {
ans = tmp;
}
for (int j = i - 2; j >= 0 && i - 1 - j + end < s.length(); j--) {
if (s.charAt(j) == s.charAt(i - j - 1 + end)) {
tmp = s.substring(j, i - j + end);
if(tmp.length() > ans.length()){
ans = tmp;
}
}
else{
break;
}
}
i = end;
}
}
return ans;
}
};
// @lc code=end
Python
#
# @lc app=leetcode.cn id=5 lang=python3
#
# [5] 最长回文子串
#
# @lc code=start
class Solution:
def longestPalindrome(self, s: str) -> str:
if(len(s) == 0):
return s
ans = s[0:1]
for i in range(1,len(s)):
j = i - 1
while(j >= 0 and 2*i-j < len(s)):
if(s[j]==s[2*i-j]):
tmp = s[j:2*i-j+1]
if(len(tmp)>len(ans)):
ans = tmp
else:
break
j -= 1
if(s[i-1]==s[i]):
end = i+1
while(True):
if(end<len(s) and s[end]==s[i]):
end += 1
else:
break
end -= 1
tmp = s[i-1:end+1]
if(len(tmp) > len(ans)):
ans = tmp
j = i - 2
while(j >= 0 and i - 1 - j + end < len(s)):
if(s[j]==s[i-j-1+end]):
tmp = s[j:i-j+end]
if(len(tmp) > len(ans)):
ans = tmp
else:
break
j -= 1
i = end
return ans
# @lc code=end