原题目
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例 1:
输入: “babad”
输出: “bab”
注意: “aba” 也是一个有效答案。
示例 2:
输入: “cbbd”
输出: “bb”
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-palindromic-substring
代码分析
动态规划:
从长度1开始,找长度1~n的所有回文串,动态规划dp[i][j]代表从i到j字符串是否是回文串
长度为1时,每个字母都是回文串dp[i][i]=true
长度为2时,只要比较两个字母是否是回文即可dp[i][j] = (s[i]==s[j])
长度大于2时,要判断中间是否是回文,以及两边字符是否相等dp[i][j]=dp[i+1][j-1]&&(s[i]==s[j])
class Solution {
public:
string longestPalindrome(string s) {
int res_len = 0;
int res_left = 0;
int n = s.size();
vector<vector<bool>>dp(n,vector<bool>(n));
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]&&res_len<l+1){
res_left = i;
res_len = l+1;
}
}
}
return s.substr(res_left,res_len);
}
};
中心扩展
奇数:以一个字符为中心,两辆比较向两边扩展至最长回文串
偶数:以两个字符为中心,两辆比较向两边扩展至最长回文串
最后返回最长回文串即可
int dp[1000][1000];
char * longestPalindrome(char * s)
{
int len = strlen(s);
memset(dp,0,sizeof(dp));
int Max=0,l=0,r=0;
for(int i=0; i<len; i++)
{
dp[i][i]=1;
if(i+1<len&&s[i]==s[i+1])
{
dp[i][i+1]=1;
if(Max<1)
{
l=i;
r=i+1;
Max=1;
}
}
}
for(int i=0,j=0; (i+j)<=2*(len-1); (i+j)%2?i++:j++)
{
int a=i,b=j;
//printf("%d %d\n",i,j);
while(a-1>=0&&b+1<len&&s[a-1]==s[b+1]&&dp[a][b])
{
dp[--a][++b]=1;
if(b-a>Max)
{
l=a;
r=b;
Max=b-a;
}
}
}
char *str;
str=(char *)malloc(sizeof(char)*1010);
int k=0;
for(int i=l; i<=r; i++)
{
str[k++]=s[i];
}
str[k]='\0';
return str;
}
c++
class Solution {
public:
void fun(string &s, int left ,int right, int len, int &res_left, int &res_len){
while(left>=0&&right<s.size()&&s[left]==s[right]){
left--;
right++;
len += 2;
}
if(res_len < len){
res_len = len;
res_left = left+1;
}
}
string longestPalindrome(string s) {
int res_len = 0,res_left = 0;
for(int i = 0; i < s.size(); i++){
fun(s,i-1,i+1,1,res_left,res_len);
fun(s,i-1,i,0,res_left,res_len);
}
return s.substr(res_left, res_len);
}
};
manache马拉车算法
待定