【经典算法题】最长回文子串
Leetcode 0005 最长回文子串
问题描述
- 问题链接:Leetcode 0005 最长回文子串
解法一
分析
-
考点:中心扩散法。
-
我们依次枚举字符串中的每个字母
s[i]
,然后让s[i]
或者(s[i], s[i+1])
为中心,向两边扩展,得到以该中心为回文串的大小,记录长度最大的回文串的起点和长度。
代码
- C++
class Solution {
public:
string longestPalindrome(string s) {
int start = 0, len = 1; // 回文串的起点和长度
for (int i = 0; i < s.size(); i++) {
int curL = max(expand(s, i, i), expand(s, i, i + 1));
if (curL > len) {
len = curL;
start = i - (curL - 1) / 2;
}
}
return s.substr(start, len);
}
int expand(string s, int i, int j) {
while (i >= 0 && j < s.size()) {
if (s[i] != s[j]) break;
i--, j++;
}
return j - i - 1;
}
};
- Java
class Solution {
public String longestPalindrome(String s) {
char[] cs = s.toCharArray();
int start = 0, len = 1; // 回文串的起点和长度
for (int i = 0; i < cs.length; i++) {
int curL = Math.max(expand(cs, i, i), expand(cs, i, i + 1));
if (curL > len) {
len = curL;
start = i - (curL - 1) / 2;
}
}
return s.substring(start, start + len);
}
private int expand(char[] s, int i, int j) {
while (i >= 0 && j < s.length) {
if (s[i] != s[j]) break;
i--; j++;
}
return j - i - 1;
}
}
- Python
class Solution:
def longestPalindrome(self, s: str) -> str:
start = 0
length = 1
for i in range(len(s)):
curL = max(self.expand(s, i, i), self.expand(s, i, i + 1))
if curL > length:
length = curL
start = i - (curL - 1) // 2
return s[start: start + length]
def expand(self, s, i, j):
while i >= 0 and j < len(s):
if s[i] != s[j]:
break
i -= 1
j += 1
return j - i - 1
时空复杂度分析
-
时间复杂度: O ( n 2 ) O(n^2) O(n2),
n
为字符串长度。 -
空间复杂度: O ( 1 ) O(1) O(1)。
解法二
分析
- 考点:马拉车算法。考点详解网址:马拉车算法。
- 原理讲解请参考上述网址,这里不再重复。
- 本题需要求解这个最长回文子串,如果在新串中
p[i]
取得了最大值,则最长回文子串的长度为len=p[i]-1
。 - 最长回文子串在原串中的起始位置为
i / 2 - 1 - (len - 1) / 2
。
代码
class Solution {
public:
string longestPalindrome(string s) {
string t = "$#";
for (auto c : s) t += c, t += '#';
t += '^';
// manacher
int n = t.size();
vector<int> p(n + 10, 0);
int mr = 0, mid;
for (int i = 1; i < n; i++) {
if (i < mr) p[i] = min(p[mid * 2 - i], mr - i);
else p[i] = 1;
while (t[i - p[i]] == t[i + p[i]]) p[i]++;
if (i + p[i] > mr) {
mr = i + p[i];
mid = i;
}
}
// 求解最长回文子串起始位置和长度
int len = 0, start = 0;
for (int i = 0; i < n; i++) {
p[i]--;
if (p[i] > len) {
len = p[i];
start = i / 2 - 1 - (l - 1) / 2;
}
}
return s.substr(start, len);
}
};
时空复杂度分析
-
时间复杂度: O ( n ) O(n) O(n),
n
为字符串长度。 -
空间复杂度: O ( n ) O(n) O(n)。