Manacher算法,O(n)。思路写在注释里了。
可能有有同学好奇为啥是O(N)的。太麻烦没自己证明,不过可以粗略体会下:
for循环毫无疑问是O(n)的,问题在于“统计未知部分”这里的while循环不好估计。
已知是统计未知部分时起始位置
由,
得,
则,
而更新时i-ans[i]<=best-ans[best]

class Solution {
public:
    /*
        Manacher算法
    */
    int getLongestPalindrome(string A, int n) {
        //加间隔符统一奇数、偶数长度的回文串,方便处理
        // 例子:cbc  --> #c#b#c#
        n=A.size()*2+1;
        char S[n+1];S[n-1]='#';S[n]=0;
        for (auto i=0;i<A.size();++i) {S[i*2]='#';S[i*2+1]=A[i];} 
        //printf("%s\n",S);
        int ans[n];ans[0]=1;// 以S[i]为起点的回文串半径
        int best=0;// 包含S[i]的、左端点最靠左的回文串
        int result=0;
        for (int i=1;i<n;++i)
        {
            ans[i]=1;
            auto j=best-(i-best);//在best回文串中i的镜像位置
            //在best镜像范围内j与i等价,直接复用之前的计算结果
            if (j<i)  ans[i]=max(ans[i],  min(ans[j],ans[best]-(best-j))    );
            //统计未知部分
            while (0<=i-ans[i]  && i+ans[i]<n && S[i-ans[i]]==S[i+ans[i]] )
                ++ans[i];
            //更新best
            if (   best+ans[best]<=i //best覆盖不了i 
                || i-ans[i]<=best-ans[best] //i的左端点更靠左
            )
                best=i;
            //统计result
            result=max(result,ans[i]-1);
        }
        return result;

    }
};