有点难度,一开始想到的两种方法都不对,花了不少时间。
先说之前的方法:
① 遍历每个点,每个点向外扩张,如果左等于右就一直扩展直到不等。
这个方法可是可以,但我没有考虑到两个相同字母也是回文串的情况(偶数长度的回文串),所以失败了,并且也没有用到考点动态规划,遂放弃。
② 用一个数组记录从这个字符前包括该点在内的回文串的最大长度,遍历每个点,然后每个点的值=上一个点的值+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;}
};