给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为1000。
示例 1:
输入: "babad"
输出: "bab"
注意: "aba"也是一个有效答案。
示例 2:
输入: "cbbd"
输出: "bb"
解决方案
方法一:暴力法
很明显,暴力法将选出所有子字符串可能的开始和结束位置,并检验它是不是回文。
复杂度分析
-
时间复杂度:O(n^3)。
-
空间复杂度:O(1)。
方法二:动态规划
我们需要维护一个二位数组dp[j][i]用来表示字符串区间[j, i]是否为回文串,当 i = j 时说明只有一个字符,是回文串;当 i = j+1 时,说明是相邻字符,只有当s[i]和s[j]相等的时候是回文串;当 i > j+1 时,只有当s[i]和s[j]相等并且dp[j+1][i-1]是回文串的时候dp[j][i]才是回文串。
class Solution {
public:
string longestPalindrome(string s) {
int len = s.length();
int dp[1000][1000] = { 0 };
int max = 0, left = 0, right = 0;
for (int i = 0; i<len; i++)
{
for (int j = 0; j<i; j++)
{
if(i == j)
dp[j][i] = 1;
else if(i == j+1)
dp[j][i] = s[j] == s[i] ? 1 : 0;
else
dp[j][i] = dp[j+1][i-1] && s[i] == s[j];
if (dp[j][i] && max < i - j + 1)
{
max = i - j + 1;
left = j;
right = i;
}
}
dp[i][i] = 1;
}
return s.substr(left, right - left + 1);
}
};
复杂度分析
-
时间复杂度:O(n^2)。
-
空间复杂度:O(n)。
最后要来的就是大名鼎鼎的马拉车算法Manacher's Algorithm,这个算法的神奇之处在于将时间复杂度提升到了O(n)这种逆天的地步,而算法本身也设计的很巧妙,很值得我们掌握,参见我另一篇专门介绍马拉车算法的博客Manacher's Algorithm 马拉车算法。