zoukankan      html  css  js  c++  java
  • manacher小结

    P3805 【模板】manacher算法

    题目大意

    n个字符组成的字符串,求最长回文串

    $O$$($$n^3$$)$

    枚举两端点,暴力往中间搜

    $O$$($$n^2$$)$

    枚举回文串终点,暴力往两边搜

    $O$$($$n$$)$

    $first:$

    $j$与$i$关于$pos$对称,$S$为以$pos$为中间的回文串,$Maxright$为$S$的右端点,$s_1$为以$j$为中间的回文串

    $s_2$为以$i$为中间的回文串

    下面开始将$manacher$,要降低复杂度,就要减少重复的操作

    $(1)$ $s_1$被$S$包含(且没到端点)

    显然根据回文的性质$len_{s_1}$=$len_{s_2}$

    $(2)$  $s_1$超过或触及端点

    这时,我们只能确定,两条蓝线之间的部分(即不超过$Maxright$的部分)是回文的

    于是从这个长度开始,从$i$的左右两边搜一遍,当左右字符不同,或者到达边界时停止

     

    $(3)$ 当$i$在$Maxright$的右边

    $s_2$还没有任何部分被访问过,只能从$i$的左右两边搜一遍,当左右字符不同,或者到达边界时停止

     ps:记得要时刻更新$Maxright$和$pos$

    My complete code: 

    #include<cstdio>
    #include<cstring>
    using namespace std;
    int n,ans; int hw[22000010];
    char a[11000010],s[22000010];
    inline int MIN(int g1,int g2){
        return g1<=g2?g1:g2;
    }
    inline int MAX(int g1,int g2){
        return g1>=g2?g1:g2;
    }
    inline void change(){
        s[0]=s[1]='#';
        for(int i=0;i<n;i++){
            s[i*2+2]=a[i];
            s[i*2+3]='#';
        }
        n=n*2+2;
        s[n]=0;
    }
    inline void manacher(){
        int maxright=0,mid=0;
        for(int i=1;i<n;i++){
            if(i<maxright)
                hw[i]=MIN(hw[(mid<<1)-i],maxright-i);
            else
                hw[i]=1;
            while(s[i+hw[i]]==s[i-hw[i]])
                ++hw[i];
            if(hw[i]+i>maxright){
                maxright=hw[i]+i;
                mid=i;
            }
        }
    }
    int main(){
        scanf(" %s",a);
        n=strlen(a);
        change();
        manacher();
        for(int i=0;i<n;++i)
            ans=MAX(ans,hw[i]);
        printf("%d",ans-1);
        return 0;
    }
    

      

  • 相关阅读:
    Java面经
    关于MarkDown语法
    JQuery
    Filter & Listener
    JSP & EL & JSTL
    Cookie & Session
    Servlet & HTTP
    Tomcat
    XML
    BootStrap
  • 原文地址:https://www.cnblogs.com/y2823774827y/p/10100374.html
Copyright © 2011-2022 走看看