最长回文子串
题目描述
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例 1:
输入: “babad”
输出: “bab”
注意: “aba” 也是一个有效答案。
示例 2:
输入: “cbbd”
输出: “bb”
解法一
暴力枚举,枚举每一个子串,并验证其是否为回文子串。
解法二:动态规划
令dp[i][j]表示从第i个字符到第j个字符的子串是否为回文子串。状态转移方程为:
边界条件为:
然后进行状态转移即可。
解法三:中心扩散
注意到每一个回文子串都是从单一字符或两个相同字符向四周扩散而来,所以只需要验证对称子串即可。
代码一
class Solution {
public:
string longestPalindrome(string s) {
int len = s.length();
string result = "";
if (len == 0) return result;
//if (len == 1) return s;
for (int i = len; i >= 1; i--)
{
for (int j = 0; j <= len - i; j++) {
if (isPalindrome(s, j, j + i - 1))
{
for (int m = j; m <= j + i - 1; m++) {
result += s[m];
}
return result;
}
}
}
return result;
}
bool isPalindrome(string s,int start,int end) {
string pre = "";
for (int i = start; i <= end; i++)
{
pre += s[i];
}
string rever = "";
for (int i = end-start; i >= 0; i--)
{
rever += pre[i];
}
return (pre == rever);
}
};
代码二
class Solution {
public:
string longestPalindrome(string s) {
int n = s.size();
vector<vector<int>> dp(n, vector<int>(n));
string ans;
for(int l = 0;l<n;++l){
for(int i = 0;i+l<n;++i){
int j = i+l;
if(l == 0) dp[i][j] = 1;
else if(l == 1) dp[i][j] = (s[i] == s[j]);
else dp[i][j] = ((s[i] == s[j]) && dp[i+1][j-1]);
if(dp[i][j] && l+1>ans.size()) ans = s.substr(i,l+1);
}
}
return ans;
}
};
代码三
class Solution {
public:
string longestPalindrome(string s) {
int n = s.size();
int l,r;
string ans;
for(int i = 0;i<n;++i){
l = i-1;r = i+1;
while(l>=0&&r<n){
if(s[l]!=s[r]) break;
--l;++r;
}
if(r-l-1>ans.size()) ans = s.substr(l+1,r-l-1);
}
for(int i = 0;i<n-1;++i){
if(s[i] == s[i+1]){
l = i-1;r = i+2;
while(l>=0&&r<n){
if(s[l]!=s[r]) break;
--l;++r;
}
if(r-l-1>ans.size()) ans = s.substr(l+1,r-l-1);
}
}
return ans;
}
};