字符串算法

Manacher-------快速查找回文串

这个算法其实是基于暴力查找回文串的优化。

	while(i-k>=0&&i+k<n&&s[i-k]==s[i+k]){
            k++;
        }

这就是暴力查找以s[i]为中心点的奇数长的回文串,偶数也一样就是改一下下角标就可以。

这个算法的优化其实就是以s[i]为中点的回文串,左右两边会有相同的回文串特点,也就是d1[i-k]=d1[i+k],但是要注意一个情况,i-k的回文串长度可能会超出当前这个i的回文串,那左边满足的右边就不一定满足。

k=min(d1[l+r-i],r-i+1);
这句就是在规避这一情况。

一旦当前位置已经跑出上一个回文串的范围就只能用暴力跑新的回文串,没有可以继承的和它对称的左半部分的回文串中心了。

for(int i=0,l=0,r=-1;i<n;i++){//跑的是奇数长度的回文串
        int k;
        if(i>r){
            k=1;//上次的回文串已经结束了,只能暴力跑
        }
        else{
            k=min(d1[l+r-i],r-i+1);//有可能左边那个点的回文串长度超出上次的回文串的边界
        }
        while(i-k>=0&&i+k<n&&s[i-k]==s[i+k]){
            k++;
        }
        //k--;
        d1[i]=k--;

        if(i+k>r){//更新回文串范围
            l=i-k;
            r=i+k;
        }
    }
for(int i=0,l=0,r=-1;i<n;i++){//偶数长度的回文串
        int k;
        if(i>r){
            k=0;
        }
        else{
            k=min(d2[l+r-i+1],r-i+1);
        }
        while(i-k-1>=0&&i+k<n&&s[i-k-1]==s[i+k]){
            k++;
        }
        //k--;
        d2[i]=k--;

        if(i+k>r){
            l=i-k-1;
            r=i+k;
        }
    }

偶数和奇数的差别就是边界的判断,偶数相当于就是把后面那个字符当做字符串中心。

posted @ 2024-03-31 17:06  zyzzzzlh  阅读(30)  评论(0)    收藏  举报