中心扩展法
时间复杂度O(n^2),空间复杂度O(1)
核心代码
int getLongestPalindrome(char* A ) {
int len;
for(len=0;A[len];++len) ;
int ans=0;
for(int t=0;t<len;++t)
{
int cur=1;
for(int i=1;i<=t&&i<=len-t-1;++i)
{
if(A[t-i]==A[t+i]) cur+=2;
else break;
}
if(cur>ans) ans=cur;
cur=0;
for(int i=1;t+1-i>=0&&t+i<len;++i)
{
if(A[t+1-i]==A[t+i]) cur+=2;
else break;
}
if(cur>ans) ans=cur;
}
return ans;
}
Mancher算法
时间复杂度O(n),空间复杂度O(n)
我的代码
int getLongestPalindrome(string A) {
int n=A.length();
string T;
for(int i=0;i<2*n+1;++i){
if(i&1) T.push_back(A[i/2]);
else T.push_back('#');
}
vector<int> len(2*n+1);
len[0]=1;
int maxpos=0,mid=0;
int res=1;
for(int i=1;i<2*n+1;++i){
if(i<maxpos&&len[2*mid-i]<maxpos-i+1){
len[i]=len[2*mid-i];
}
else{
if(i>=maxpos) maxpos=i;
while(maxpos+1<2*n+1&&2*i-maxpos-1>=0&&T[maxpos+1]==T[2*i-maxpos-1]){
++maxpos;
}
mid=i;
len[i]=maxpos-i+1;
}
res=max(len[i]-1,res);
}
return res;
}
牛客官方
void manacher(string& s, int n, vector<int>& mp){
string ms = "";
ms += "$#";
//预处理
for(int i = 0; i < n; i++){
//使之都变成奇数回文子串
ms += s[i];
ms += '#';
}
//目前已知的最长回文子串的最右一位的后一位
int maxpos = 0;
//当前的最长回文子串的中心点
int index = 0;
for(int i = 0; i < ms.length(); i++){
mp[i] = maxpos > i ? min(mp[2 * index - i], maxpos - i) : 1;
//两边扫
while(ms[i + mp[i]] == ms[i - mp[i]])
mp[i]++;
//更新位置
if(i + mp[i] > maxpos){
maxpos = i + mp[i];
index = i;
}
}
}
int getLongestPalindrome(string A) {
int n = A.length();
//记录回文子串长度
vector<int> mp(2 * n + 2);
manacher(A, n, mp);
int maxlen = 0;
//遍历数组
for(int i = 0; i < 2 * n + 2; i++)
//找到最大的长度
maxlen = max(maxlen, mp[i] - 1);
return maxlen;
}
区别
牛客代码在转化后串前面加了一个特殊字符,用来防止下标小于0越界
牛客代码进行再探查时变化的是len[i],我的代码变化的是maxpos