題目簡析:找出最長迴文子串,首先要注意的是,迴文子串有奇迴文和偶迴文兩種情況,也就是說,無論是奇迴文還是偶迴文,我們都要各查找一遍,輸出最長的答案。當然,當input是空字符串的時候ouput和input也是空字符串,但是input的字符串只有一個字母或者兩個不同字母時,output是input的首字母,因爲只有一個字母也是奇迴文字符串,長度相同,這裏默認優先輸出位置靠前的迴文字符串。
分析到這裏,問題就只剩下如何查找和記錄的問題。首先分析迴文字符串的特點,它的特點就是有一個“對稱點”,從對稱點往兩端看的話,字母也是對稱相同的,那麼我們的解題思路可以從找“對稱點”出發。
對於奇迴文字符串,我們可以從i=0開始,檢索字符串s中的s[i]是否等於s[i+2],假如找到這樣的對稱點後,我們記錄字符串首尾標記m、n,分別是對稱起點的首尾i和i+2(後面m、n會變化,使字符串增長),不斷進行m-1和n+1操作,看能否繼續找到s[m]=s[n]首尾字母並加入,實現增長。當字符串無法再找到新的相同的首尾字母,說明此次查找到的奇迴文字符串已經到達最長長度,假如比已有的最長奇迴文字符串odd_max長,那麼更新odd_max,反之則odd_max不變。
查找完,重新查找一個不同的迴文串當然不難,這裏還有一個難點就是關於迴文字符串嵌套以及部分重疊的問題,爲了確保所有可能的迴文串都會被檢索,我們就要確保任何可能存在的對稱點都要被檢查到,因此每一次查找結束一個迴文字符串,要從上一個對稱點右邊鄰近處開始檢索,而不能從迴文串結尾處開始查找新的對稱點。
比如正確應該從上一個對稱點右邊一位開始查找,如下圖
而在上一個迴文串結尾處開始查找新的對稱點是錯的,如下
對於偶迴文字符,與奇迴文字符串查找方式相同,唯一的不同點是對稱點的查找是查找s[i]是否等於s[i+1],而不是s[i+2]。
經過以上兩次遍歷查找,可以得到最長奇迴文串odd_max和最偶迴文串even_max,輸出兩者間最長者即可。
以下貼上代碼,僅供參考
class Solution {
public:
string longestPalindrome(string s) {
int i,m,n,length;
string odd_max="";
string even_max="";
length=s.length();
odd_max.assign(s,0,1);
i=0;
if(s.length()==1)
return s;
while(i<length-2){
if(s[i]!=s[i+2])
i++;
else{
m=i;n=i+2;
while(m>=0 && n<=length-1){
if(s[m]==s[n]){
m--;n++;
}
else
break;
}
if((n-m-2)>odd_max.length())
odd_max.assign(s,m+1,n-m-1);
i++;
}
}
i=0;
while(i<length-1){
if(s[i]!=s[i+1])
i++;
else{
m=i;n=i+1;
while(m>=0 && n<=length-1){
if(s[m]==s[n]){
m--;n++;
}
else
break;
}
if((n-m-2)>even_max.length())
even_max.assign(s,m+1,n-m-1);
i++;
}
}
if(odd_max.length()>=even_max.length())
return odd_max;
else
return even_max;
}
};
Submission Result: Accepted
Runtime: 0 ms
題目鏈接:https://leetcode.com/problems/longest-palindromic-substring/description/