地址:https://leetcode-cn.com/problems/longest-palindromic-substring/
思路:一:直接暴力,遍历回文字符串的中心位置,在由中心位置向外展开判断即可
二:manacher算法,见https://blog.csdn.net/dyx404514/article/details/42061017
利用前面已经求得的最右回文串来求解当前位置的回文串,达到O(n)复杂度
三:可以用dp来写,不过没必要。。复杂度为 O(n^2)
dp[i][k] 表示以s[i-1]为左端点的长度为k的字符串是否为回文字符串
Code:
#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
typedef long long LL;
/*
class Solution { //O(n^2)
public:
string longestPalindrome(string s) {
string res="";
int n=s.length();
int Max=1,l=0,r=0;
for(int i=0;i<n;++i)
{
for(int j=1;i-j>=0&&i+j<n&&s[i-j]==s[i+j];++j)
if(Max<j+j+1){
Max=j+j+1;
l=i-j; r=i+j;
}
for(int j=0;i-j>=0&&i+j+1<n&&s[i-j]==s[i+j+1];++j)
if(Max<j+j+2){
Max=j+j+2;
l=i-j; r=i+j+1;
}
}
res=string(s,l,r-l+1);
return res;
}
};
*/
class Solution { //Manacher算法 O(n)
public:
string longestPalindrome(string s) {
string res="";
int n=s.length(),len=0;
char a[n*2+55];
int d[n*2+55];
for(int i=0;i<n;++i)
{
a[len++]='#';
a[len++]=s[i];
}
a[len++]='#';
int r=0,p=0;
d[0]=1;
int L=0,R=-1,Max=0;
for(int i=0;i<len&&r<len;++i)
if(i<=r&&d[2*p-i]<r-i){
d[i]=d[2*p-i];
}else{
int k=max(0,r-i);
while(i-k>=0&&i+k<len&&a[i-k]==a[i+k]){
d[i]=k+1; ++k;
}
p=i; r=i+d[i]-1;
if(Max<d[i]){
Max=d[i];
L=i-d[i]+1; R=r;
}
}
while(L<=R){
if(a[L]!='#') res+=a[L];
++L;
}
return res;
}
};
int main()
{
string str;
Solution So;
cin>>str;
cout<<So.longestPalindrome(str)<<endl;
return 0;
}
DP:
#include<iostream>
using namespace std;
const int MAX_N=1e3+5;
int n;
string str;
int dp[MAX_N][3];
int main()
{
ios::sync_with_stdio(false);
cin>>str;
n=str.size();
for(int i=1;i<=n;++i)
dp[i][0]=dp[i][1]=1;
int ans=1;
for(int k=2;k<=n;++k)
for(int i=1;i+k-1<=n;++i)
if(dp[i+1][(k+1)%3]&&str[i-1]==str[i+k-2]) dp[i][k%3]=1,ans=k;
else dp[i][k%3]=0;
printf("%d\n",ans);
return 0;
}