- 最长回文子串:找到最长的回文子串
动态规划一:
class Solution {
public:
string longestPalindrome(string s) {
int n = s.size();
vector<vector<int>> dp(n, vector<int>(n));
string result;
// delta间距或者跨度
for (int delta = 0;delta < n;++delta) {
for (int i = 0;i + delta < n;++i) {
int j = i + delta;
if (delta == 0) {
dp[i][j] = true;
} else if (delta == 1) {
dp[i][j] = s[i] == s[j];
} else {
dp[i][j] = s[i] == s[j] && dp[i+1][j-1];
}
// 原回文串长度小于跨度则更新串
if (dp[i][j] && result.size() < delta + 1) {
result = s.substr(i, j + 1);
}
}
}
return result;
}
};
时间复杂度:O(n^2);空间复杂度:O(n^2);
方法二:回文中心往外扩展
class Solution {
public:
string longestPalindrome(string s) {
int n = s.size();
int start = 0, end = 0;
for (int i = 0;i < n; ++i) {
// 从中间开始
auto [l1, r1] = expandStr(s, i, i);
// 从中间俩个相等字符开始
auto [l2, r2] = expandStr(s, i, i+1);
if (r1 - l1 > end - start) {
start = l1;
end = r1;
}
if (r2 - l2 > end - start) {
start = l2;
end = r2;
}
}
return s.substr(start, end - start + 1);
}
pair<int, int> expandStr(string s, int left, int right) {
int n = s.size();
while(--left >= 0 && ++right <= n) {
if (s[left] != s[right]) {
break;
}
}
return {left + 1, right - 1};
}
};
方法三:Manacher算法:填充字符串变为奇数位
class Solution {
public:
int expand(const string& s, int left, int right) {
while (left >= 0 && right < s.size() && s[left] == s[right]) {
--left;
++right;
}
return (right - left - 2) / 2;
}
string longestPalindrome(string s) {
int start = 0, end = -1;
string t = "#";
for (char c: s) {
t += c;
t += '#';
}
t += '#';
s = t;
vector<int> arm_len;
int right = -1, j = -1;
for (int i = 0; i < s.size(); ++i) {
int cur_arm_len;
if (right >= i) {
// i关于j对称点
int i_sym = j * 2 - i;
// right大于i时,可从臂长缓存获取对称点臂长,和剩余右端长度取最小值
// 获取i的臂长
int min_arm_len = min(arm_len[i_sym], right - i);
// 从i开始进行臂长范围外扩展
cur_arm_len = expand(s, i - min_arm_len, i + min_arm_len);
} else {
// 从i奇数扩展 获取臂长
cur_arm_len = expand(s, i, i);
}
// 位置点i所对应臂长
arm_len.push_back(cur_arm_len);
if (i + cur_arm_len > right) {
j = i;
right = i + cur_arm_len;
}
if (cur_arm_len * 2 + 1 > end - start) {
start = i - cur_arm_len;
end = i + cur_arm_len;
}
}
string ans;
for (int i = start; i <= end; ++i) {
if (s[i] != '#') {
ans += s[i];
}
}
return ans;
}
};