版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/liuweiyuxiang/article/details/83142939
1 题目
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为1000。
示例 1:
输入: “babad”
输出: “bab”
注意: "aba"也是一个有效答案。
示例 2:
输入: “cbbd”
输出: “bb”
题目链接:
https://leetcode-cn.com/problems/longest-palindromic-substring/description/
2 解法
2.1 中心扩展法
class Solution {
public:
string longestPalindrome(string s) {
if(s == NULL || s.size() <= 1)
return s;
int start = 0;
int end = 0;
for(int i = 0; i < s.size(); i++){
int len1 = maxlen(s,i,i);
int len2 = maxlen(s,i,i+1);
int len = len1 > len2 ? len1 : len2;
//cout<<"len:"<<len<<endl;
if(len > end - start){ # 新的子串余当前子串长度相等就更新,如果有几个相同长度的子串,找出的是最后一个;如果写成if(len > end - start),则新的子串大于当前子串长度才更新,如果有几个相同长度的子串,找出的是最前一个
//cout<<"start:"<<start<<" end:"<<end<<endl;
start = i - (len - 1)/2;
end = i + len / 2;
}
}
return s.substr(start,end-start+1);
}
int maxlen(string s,int i,int j){
int left= i;
int right=j;
while(left >= 0 && right < s.size() && s[left] == s[right]){
left--;
right++;
}
return right - left - 1;
}
};
2.2 动态规划法
class Solution {
public:
string longestPalindrome(string s) {
if(s.size() == 0)
return s;
const int n=s.size();
bool dp[n][n];
fill_n(&dp[0][0],n*n,false);
int max_len=1; //保存最长回文子串长度
int start=0;//保存最长回文子串起点
for(int i=0;i<s.size();++i)
{
for(int j=0;j<=i;++j)
{
if(i-j<2)
dp[j][i]=(s[i]==s[j]);
else
dp[j][i]=(s[i]==s[j] && dp[j+1][i-1]);
if(dp[j][i] && max_len<(i-j+1))
{
max_len=i-j+1;
start=j;
}
}
}
return s.substr(start,max_len);
}
};
解析:回文串就是正着读和反着读一样的字符串,如“abba”,“abcba”,最长回文子串是字符串的子串中最长的属于回文串的子串。如字符串"abbaabccba"的最长回文子串为"abccba",本文采用动态规划算法来查找最长回文子串,算法时间复杂度为O(n²)。**设状态dp[j][i]表示索引j到索引i的子串是否是回文串。**则易得转移方程如下:
则dp[j][i]为true时表示索引j到索引i形成的子串为回文子串,且子串起点索引为i,长度为j+i-1。
2.3 暴力求解法
暴力求解就是列举出s的左右子串,判断是否是回文子串,如果是判断其长度是否大于找到的上一个回文子串,大于则更新否则不更新。
参考博客:动态规划算法求最长回文子串