https://leetcode-cn.com/problems/longest-palindromic-substring/
思路一: d p dp dp,如果 s [ i … j ] s[i…j] s[i…j]是回文串,那么 d p [ i ] [ j ] = 1 dp[i][j]=1 dp[i][j]=1,否则 d p [ i ] [ j ] = 0 dp[i][j]=0 dp[i][j]=0,显然 d p [ i ] [ i ] = 1 dp[i][i]=1 dp[i][i]=1,接下来枚举区间长度 l e n len len和起始点 i i i,那么终止点就是 j = i + l e n − 1 j=i+len-1 j=i+len−1,只要 s [ i ] = s [ j ] s[i]=s[j] s[i]=s[j]且 d p [ i + 1 ] [ j − 1 ] = 1 dp[i+1][j-1]=1 dp[i+1][j−1]=1就说明 s [ i … j ] s[i…j] s[i…j]是回文串,复杂度 O ( n 2 ) O(n^2) O(n2)。
class Solution {
public:
string longestPalindrome(string s) {
int n=s.size();
vector<vector<bool>> dp(n,vector<bool>(n));
int start=0,maxlen=1;
dp[0][0]=1;
for(int i=1;i<n;i++)
{
dp[i][i]=1;
if(s[i]==s[i-1])
{
dp[i-1][i]=1;
start=i-1;
maxlen=2;
}
}
for(int len=3;len<=n;len++)
{
for(int i=0;i+len-1<n;i++)
{
int j=i+len-1;
if(s[i]==s[j]&&dp[i+1][j-1])
{
dp[i][j]=1;
if(j-i+1>maxlen)
maxlen=j-i+1,start=i;
}
}
}
return s.substr(start,maxlen);
}
};
思路二:考虑回文串的性质,我们可以从中间点向两边扩展从而判断一个字符串是否是回文串,那么对于长度为 n n n的字符串来说,其中间点一共有 2 ∗ n − 1 2*n-1 2∗n−1种选择,具体一点: 1. 1. 1.以某个字符作为中心,这有 n n n种选择; 2. 2. 2.以相邻两个字符的中间作为中心,这有 n − 1 n-1 n−1种选择。枚举即可,复杂度 O ( n 2 ) O(n^2) O(n2)。
class Solution {
public:
string longestPalindrome(string s) {
int n=s.size();
int start=0,maxlen=1;
for(int i=0;i<n;i++)
{
int tmp=calLen(s,i,i);
if(tmp>maxlen)
maxlen=tmp,start=i-(tmp>>1);
tmp=calLen(s,i,i+1);
if(tmp>maxlen)
maxlen=tmp,start=i-(tmp>>1)+1;
}
return s.substr(start,maxlen);
}
int calLen(const string &s,int l,int r)
{
int ml=0,mr=s.size()-1;
while(l>=ml&&r<=mr&&s[l]==s[r])
--l,++r;
return r-l-1;
}
};
思路三:马拉车算法,参见文章。
class Solution {
public:
string longestPalindrome(string s) {
string t="#";
int n=s.size();
for(int i=0;i<n;i++)
{
t+=s[i];
t+="#";
}
n<<=1;
vector<int> len(n+1);
int l=0,r=-1,k;
int start=0,maxlen=1;
for(int i=0;i<=n;i++)
{
k=i>=r?1:min(len[l+r-i],r-i);
while(0<=i-k&&i+k<=n&&t[i-k]==t[i+k])
++k;
len[i]=--k;
if(i+k>r)
l=i-k,r=i+k;
if(len[i]>maxlen)
{
maxlen=len[i];
start=(i-maxlen)>>1;
}
}
return s.substr(start,maxlen);
}
};