题目简析:找出最长回文子串,首先要注意的是,回文子串有奇回文和偶回文两种情况,也就是说,无论是奇回文还是偶回文,我们都要各查找一遍,输出最长的答案。当然,当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/