[5]. 最长回文子串
- 题目
- 算法设计:双指针
- 算法设计:Manacher 算法
题目
传送门:https://leetcode.cn/problems/longest-palindromic-substring/
算法设计:双指针
检查回文串的通用解决方案是,双指针。
寻找回文串的思想是:从中间开始向俩边扩散来判断回文串。
回文串在长度为奇数和偶数的时候,中心不一样:
- 奇数回文串的「中心」是一个具体的字符,如回文串
aba
的中心是字符b
; - 偶数回文串的「中心」是位于中间的两个字符的「空隙」,如回文串
abba
的中心是两个b
,也可以看成两个b
中间的空隙。
for(int i=0; i<len(s); i++) // 枚举每个点
奇数:找到以 s[i] 为中心的回文串
偶数:找到以 s[i] 和 s[i+1] 为中心的回文串
根据找到的回文串,更新最长子串
代码实现:
class Solution {
string res;
public:
string mid(string& s, int l, int r) { // 中心扩散,俩指针可同时处理回文长度为奇数、偶数情况
while( l>=0 && r<s.size() && s[l] == s[r] ) // 如果对应相等,判断边界合法 && 是回文,顺序不能变,必须先判断边界,再判断回文,如 l=0,s[0-1]就会越界
l --, r ++; // 从中心扩散,去探下一个位置
return s.substr( l + 1, r - l - 1 ); // 最长回文串,从指定位置开始,复制指定的长度
}
string max3(string res, string s1, string s2) { // 寻找最长串
res = res.size() > s1.size() ? res : s1;
res = res.size() > s2.size() ? res : s2;
return res;
}
string longestPalindrome(string s) {
for(int i=0; i<s.size(); i++) { // 枚举所有的中心点
string s1 = mid(s, i, i); // 寻找奇数回文子串
string s2 = mid(s, i, i+1); // 寻找偶数回文子串
res = max3(res, s1, s2); // 寻找最长回文子串
}
return res;
}
};
时间复杂度:
空间复杂度:
算法设计:Manacher 算法
马拉车算法的思想是在中心扩散的基础上减少重复判断一一记录最新且边界最右回文子串的右边界和中心,那么根据回文的对称性,在该子串中心以右但不超出右边界的待验证子串可以用该子串中心以左的已验证子串来验证,超出右边界的待验证子串则进行朴素匹配。