一直觉得会非常难的题目,没有想到会如此简单。
既然要找最长的回文子串,那么是不是就只要找到合适的中心线,然后依次往外扩展。
比如abcba, 中心线为c的时候,依次往外扩展。就能找到最长的回文子串了那?
这样的话就转换为寻找中心线的问题了。
不过中心线不一定是在字母上,也有可能是在两个字母之间。
这样也能理解,找最长的回文子串。有可能是以中心字母开始往两边扩展。
也有可能是abba这样中间两个字母往外扩展。
所以两个不同的中心线的方法都要考虑。
一下就是代码了。
class Solution {
public:
string getPalindronme(int start,int end,string s)
{
while(start >=0 && end < s.length() && s[start] == s[end]) {
start--;
end++;
}
//跳出循环的唯一原因就是当前start 到 end 已经破坏了回文。返回前一个状态(已经是回文状态并取出字符)
return s.substr(start+1, end-start-1);
}
string longestPalindrome(string s) {
//使用中心线算法去做这个题目。
//但是中心线有两种, 以某个字母为中心向两边展开
//2 以两个字母中间为中心线向两边展开。
if(s.length() <2)
return s;
string longPalind = "";
//go through each position to find the 中心线
for(int i =0;i<s.length();i++) {
//odd
int start = i;
int end = i;
string curPalind = getPalindronme(start, end, s);
if(curPalind.length() > longPalind.length())
longPalind = curPalind;
//even
start = i;
end = i+1;
curPalind = getPalindronme(start, end, s);
if(curPalind.length() > longPalind.length())
longPalind = curPalind;
}
return longPalind;
}
};
顺便带个DP的解法,生成一个二维数组。来记录i到j之间是否是回文。
这样来算出来最长的。
既然用DP,就得初始化矩阵。
首先,字母i到i 肯定是回文。
其次i到i+1可能判断是否是回文。
地推公式就是
[i][j] = [i+1][j-1] && s[i] == s[j]
class Solution {
public:
string longestPalindrome(string s) {
int n = s.length();
if(n<2)
return s;
int start=0;
int longest=1;
vector<vector<bool>> isPalindrome(n, vector<bool> (n, false));
for(int i=0;i<n;i++) {
isPalindrome[i][i] = true;
}
for(int i=0;i<n-1;i++){
isPalindrome[i][i+1] = (s[i] == s[i+1]);
if(isPalindrome[i][i+1] == true){
start =i;
longest = 2;
}
}
for(int i=n-2;i>=0;i--) {
for(int j=i+2;j<n;j++){
isPalindrome[i][j] = isPalindrome[i+1][j-1] && (s[i] == s[j]);
if(isPalindrome[i][j] == true) {
if(j-i+1 > longest) {
start = i;
longest = j-i+1;
}
}
}
}
return s.substr(start, longest);
}
};