题目描述
5.最长回文子串
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例1
输入: “babad”
输出: “bab”
注意: “aba” 也是一个有效答案。
示例2
输入: “cbbd”
输出: “bb”
解题思路
1.暴力法
- 定义一个函数 IsPalindrome 来判断某个子串是否为回文子串,如果是回文子串 return true ,否则 return false
- 使用两个循环暴力遍历整个字符串 s , 找出 s 中最长的回文子串作为 ans 返回
- 时间复杂度: O(n^3)
- 由于时间复杂度过高,未能通过全部测试
代码如下
class Solution {
public:
string longestPalindrome(string s) {
string ans = "";
for(int i = 0; i < s.length(); i++)
{
string temp = "";
for(int j = i; j < s.length(); j++)
{
if(IsPalindrome(s, i, j))
{
temp = s.substr(i,(j-i+1));
}
}
ans = ans.length() > temp.length() ? ans : temp;
}
return ans;
}
bool IsPalindrome(string s, int left,int right)
{
while(left < right)
{
if(s[left] != s[right])
{
return false;
}
else
{
left++;
right--;
}
}
return true;
}
};
2.动态规划
- 定义动态二位数组: dp[i][j] 表示从i 到 j 的子串,若为回文,则 dp[i][j] == 1
- 对于给定的一个字符串,首先每个单独的字符都是回文子串 dp [ i ][ i ] == 1
- 判断相邻连个字符是否相同,若相同,则为回文子串 dp [ i ][ i + 1] == 1
- 接下来判断长度大于2的子串,若 s[i] == s[j] 且 dp[i+1][j-1] == 1 , 则 dp[i][j] 为回文子串,且更新长度 length = j - i + 1
- 时间复杂度: O(n^2)
代码如下
class Solution {
public:
string longestPalindrome(string s) {
int start = 0;
int length = 1;
vector<vector<int>> dp(s.length(), vector<int>(s.length()));
for(int i = 0; i < s. length(); i++)
{
dp[i][i] = 1; //每一个单独的字符都是回文子串
if(s[i] == s[i + 1] && i < s.length() - 1) //判断相邻两个字符的子串是否为回文子串
{
dp[i][i + 1] == 1;
length = 2;
start = i;
}
}
for(int l = 3; l < s.length(); l++)
{
for(int i = 0; i + l - 1 < s.length(); i++) //字符串起始位置
{
int j = i + l - 1; //字符串截至位置
if(s[i] == s[j] && dp[i + 1][j - 1] == 1)
{
dp[i][j] = 1;
start = i;
length = l;
}
}
}
return s.substr(start, length);
}
};