算法题目:
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例 1:
输入: “babad”
输出: “bab”
注意: “aba” 也是一个有效答案。
示例 2:
输入: “cbbd”
输出: “bb”
算法思路:
观察回文串的特点,其必定以某字符为中心完全对称,如:"abba"以"bb"为中心对称,"aba"以"b"为中心对称,"abba"以"bb"为中心对称,"abbba"以"bbb"为中心对称。
故我们只需遍历以所有字符(or 多个相连重复字符)为中心的子串(遍历时可将多个相连重复字符视为一个中心字符),并判定其是否为回文串,若是回文串,则将其长度与以前一字符为中心时的最大长度max_len进行比较,长度更大则更新max_len,长度更小则保留原来的max_len。用left和right记录以s[index]为中心的回文子串的最左端和最右端,因此回文子串长度为 (right - 1) - (left + 1) + 1 = right-left-1。
算法步骤如下:
1)从index=0开始遍历字符串,用left和right记录以s[index]为中心的回文子串的最左端和最右端,left=index-1,right=index+1;
2)以index为起始位置向右计数所有与s[index]相等且连续的字符,若有多个相等连续字符则以多个相等字符为中心,right指向中心字符串的下一个字符,而left指向中心字符串的前一个字符。若仅以一个字符为中心,则left和right不变。循环执行4);
3)定位下一个中心index,下一个中心为单个字符或重复字符串的下一个字符。
4)比较s[left]与s[right],若相等则left–,right++,直至两者不相等或left与right超出索引范围循环结束,更新max_len的值,并记录该子串的开始位置start=left+1。
代码实现:
class Solution {
public:
string longestPalindrome(string s) {
if(s == "") return "";
int start = 0;
int left = 0;
int right = 0;
int max_len = 0;
int index = 0;
while(s[index]){
right = index + 1;
left = index - 1;
//从当前字符开始往右读取连续重复字符
//(连续重复字符必定能构成回文子串,也必定是回文子串的一部分)
//如"abbaa" 中从索引1开始的连续重复字符是"bb",从索引3开始连续重复字符是'aa'
while(s[right] == s[index]){
right ++;
}
//定位下一个子串的中心
index = right;
while(left >= 0 && right <= s.size() && s[left] == s[right]){
left --;
right ++;
}
if(right - left - 1 > max_len){
start = left + 1;
max_len = right - left - 1;
}
}
return s.substr(start, max_len);
}
};