Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
Example 1:
Input: “babad”
Output: “bab”
Note: “aba” is also a valid answer.
Example 2:
Input: “cbbd”
Output: “bb”
传统的验证回文串的方法就是两个两个的对称验证是否相等,那么对于找回文字串的问题,就要以每一个字符为中心,像两边扩散来寻找回文串,这个算法的时间复杂度是O(n*n),可以通过OJ,就是要注意奇偶情况,由于回文串的长度可奇可偶,比如"bob"是奇数形式的回文,"noon"就是偶数形式的回文,两种形式的回文都要搜索,对于奇数形式的,我们就从遍历到的位置为中心,向两边进行扩散,对于偶数情况,我们就把当前位置和下一个位置当作偶数行回文的最中间两个字符,然后向两边进行搜索。
我们要定义两个变量start和maxLen,分别表示最长回文子串的起点跟长度,在遍历s中的字符的时候,我们首先判断剩余的字符数是否小于等于maxLen的一半,是的话说明maxLen无法再变长了,直接break掉。否则就要继续判断,我们用两个变量left和right分别指向当前位置,然后我们先要做的是向右遍历跳过重复项,这个操作很必要,比如对于 noon,i在第一个o的位置,如果我们以o为最中心往两边扩散,是无法得到长度为4的回文串的,只有先跳过重复,此时left指向第一个o,right指向第二个o,然后再向两边扩散。而对于 bob,i在第一个o的位置时,无法向右跳过重复,此时left和right同时指向o,再向两边扩散也是正确的,所以可以同时处理奇数和偶数的回文串,之后的操作就是更新maxLen和start了。
#include<iostream>
using namespace std;
#include<string>
class Solution {
public:
string longestPalindrome(string s) {
if(s.size() < 2) return s;
int n=s.size(),maxLen=0,start=0; //start和maxLen,分别表示最长回文子串的起点跟长度
for(int i=0; i<n;){
if(n-i <= maxLen/2) break; //首先判断剩余的字符数是否小于等于maxLen的一半,是的话说明maxLen无法再变长了,直接break掉。否则就要继续判断。
int left=i, right=i; //我们用两个变量left和right分别指向当前位置
while(right<n-1 && s[right]==s[right+1]) ++right;
//我们先要做的是向右遍历跳过重复项,这个操作很必要,
//比如对于 noon,i在第一个o的位置,如果我们以o为最中心往两边扩散,是无法得到长度为4的回文串的,只有先跳过重复,此时left指向第一个o,right指向第二个o,然后再向两边扩散。
//而对于 bob,i在第一个o的位置时,无法向右跳过重复,此时left和right同时指向o,再向两边扩散也是正确的,所以可以同时处理奇数和偶数的回文串
i = right+1;
while(right<n-1 && left>0 && s[right+1]==s[left-1]){ //判断中心字符的左右是否相同,也就是是否回文
right++;
left--;
}
if(maxLen<right-left+1){ //maxLen就是上一次的回文串的长度,因为我们要找的是最长的回文串,所以要把现在的回文串长度right-left+1和之前的回文串长度比较大小
maxLen = right-left+1; //更新maxLen
start = left; //start是起始字符
}
}
return s.substr(start,maxLen);
}
};
int main(){
Solution S;
cout << S.longestPalindrome("babad");
return 0;
}
参考网址:https://www.cnblogs.com/grandyang/p/4464476.html
https://leetcode.com/problems/longest-palindromic-substring/