5. Longest Palindromic Substring
题目:
Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
Example 1:
Input: “babad”
Output: “bab”
Note: “aba” is also a valid answer.
Example 2:
Input: “cbbd”
Output: “bb”
即要求对于给定的一个字符串输出其最长的回文子串。
解法一:
O(n3):暴力求解,对于字符串的每个子串进行回文分析,一个n个字符的字符串有n2的子串,每个子串平均长度为n/2,所以算法时间复杂度为O(n3)。
O(n2):利用动态规划的思想,用字符 i 表示字符串中的第i个字符,用f(i,j)表示从字符 i 到字符 j 的子串是否是回文子串;
那么f(i,j) = true的情况有两种:1.i = j,即这个子串只有一个字符;2.s[i] = s[j] 并且f(i+1,j-1) = true,即子串首尾两个字符相同并且中间的子串也是回文的。
那么题目所求得最长回文子串就是在f(i,j) = true的情况下j-i最大的时候对应的子串。
通过构建一个二维数组,并且进行双循环的求解,就可以得出最终的结果,所以算法的时间复杂度和空间复杂度都是O(n2)。
class Solution {
public:
string longestPalindrome(string s) {
int n = s.length();
if(n <= 1)
return s;
bool dp[n][n];
int maxLen = 0;
int maxI = 0;
for(int j = 0;j < n;j++)
{
for(int i = 0;i <= j ;i++)
{
dp[i][j] = (s[i] == s[j] && ((j-i <= 1) || dp[i+1][j-1]));
if(dp[i][j] && j-i > maxLen)
{
maxLen = j - i;
maxI = i;
}
}
}
return s.substr(maxI,maxLen+1);
}
};
解法二:
O(n):Manacher 算法
class Solution {
public:
string longestPalindrome(string s) {
int n = s.length();
if(n <= 1)
return s;
char olds[n];
strncpy(olds,s.c_str(),n);
int newn = 2*n+1;
char news[newn];
int j = 0;
for(int i = 0;i < n;i++)
{
news[j++] = '#';
news[j++] = olds[i];
}
news[j] = '#';
int RL[newn];
int maxRight = 0;
int pos = 0;
int maxLen = 0;
int maxI = 0;
for(int i = 0;i < newn;i++)
{
if(i < maxRight)
{
RL[i] = maxRight - i;
if((maxRight - i) > RL[2*pos-i])
RL[i] = RL[2*pos-i];
}
else
RL[i] = 1;
while(i - RL[i] >= 0 && i + RL[i] < newn && news[i-RL[i]] == news[i+RL[i]])
{
RL[i]++;
}
if(RL[i] + i - 1 > maxRight)
{
maxRight = RL[i] + i - 1;
pos = i;
}
if(maxLen <= RL[i])
{
maxLen = RL[i];
maxI = i;
}
}
return s.substr((maxI-maxLen+1)/2,maxLen-1);
}
};