有點難度,一開始想到的兩種方法都不對,花了不少時間。
先說之前的方法:
① 遍歷每個點,每個點向外擴張,如果左等于右就一直擴展直到不等。
這個方法可是可以,但我沒有考慮到兩個相同字母也是回文串的情況(偶數長度的回文串),所以失敗了,并且也沒有用到考點動態規劃,遂放棄。
② 用一個數組記錄從這個字符前包括該點在內的回文串的最大長度,遍歷每個點,然后每個點的值=上一個點的值+2(若根據上一點的值回到上一點的回文串之前的那個字符和這個點的字符相同),否則為1(每個字符自身就是回文串)。
后來發現這個做法完全不行,因為有些比如acccc這種,計算最后一個c時,由于每次只會記錄最大的回文串,倒數第二個c的數是3,于是就會判定c!=a,無法記錄最長的回文串cccc。
所以還是得二維數組。
根據首位序號維護布爾類型的二維數組,每個值記錄首位字符括起來的串是否為回文串,這樣做狀態轉換方程比較難想。
自己在草稿紙上畫個二維數組就好想得多。
我的方法是將palindrome[i][j]設為第i個字符到第j個字符是否是回文串(包括邊界i和j)。
當前字符palindrome[i][j]是回文串的條件是:palindrome[i-1][j+1](意思是兩邊界縮小1位是否是回文串)并且s[j]==s[i](兩邊界自身相同)。
然后palindrome[i][i]必為回文串,如果s[i-1]=s[i],那么palindrome[i-1][i]也為回文串。
從i=1開始遍歷到結束(i是起始字符),從j=i-1開始遍歷到j=0(j是結束字符,中間字符長度要從小到大,所以j要從大到小)。
class Solution {
public:string longestPalindrome(string s) {vector<vector<bool>> palindrome(s.size(),vector<bool> (s.size(),0));int result=1;string re=s.substr(0,1);for(int i=0;i<s.size();i++){palindrome[i][i]=1;for(int j=i-1;j>=0;j--){if(j==i-1&&s[j]==s[i]) palindrome[i][j]=1;if(palindrome[i-1][j+1]==1&&s[j]==s[i]) palindrome[i][j]=1;if(palindrome[i][j]==1&&i-j+1>result){result=i-j+1;re=s.substr(j,i-j+1);}}}return re;}
};