算法題目:
給定一個字符串 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);
}
};