• Manacher算法


     

    又名马拉车算法,可以在事件复杂度O(n)的情况下求解一个字符串每个回文中心的最长回文半径

    暴力匹配:

    从原字符串的收不开始,一次向尾部进行遍历,没访问一个字符,就以此字符为中心向两边扩展,记录改点的最长回文长度。

    弊端:

    1:不适合偶数回文串:abba

    2:时间复杂度比较高O(n^2)

     

    Manncher算法本质上也是基于暴力匹配的方法,不过做了一点简单的预处理,且在扩展时提供了加速。

    预处理:在字符串每个字符两边加了’#’使字符串变成了奇数个字符串,长度变为了2n+1.预处理后的最长回文字符串的长度整数除以2就得到了原先字符串的最长回文串的长度。

    当以’#’为中心遍历就解决了偶数回文串的问题。

     

    回文半径数组radius是用来记录以每个位置的字符为回文中心求出的回文半径长度。所以#a#c#b#b#c#b#d#s#,所以radius数组为[1,2,1,2,1,2,5,2,1,4,1,2,1,2,1,2,1]

     

    一个位置最右回文右边界指的是这个位置及之前的位置的回文子串,所到达的最右边的地方。比如对于字符串#a#c#b#b#c#b#d#s#

     

    其实就是回文串最右边的下标。

    最开始的时候R=-1.到p=0的位置,回文就是其本身,最右会问边界R=0;p=1时,有回文串#a#,R=2;p=2时,R=2;P=3时,R=6;p=4时,最右回文边界还是p=3时的右边界,R=6;依此类推。

    最右回文右边界的对称中心C就是p=4时,R=6,C=3

     

    算法流程

    分为两种情况

    情况一:下一个要移动的位置在最右回文右边界 R的右边

    比如在最开始的时候R=-1,p的下一个移动的位置为p=0,p=0在R=-1的右边;p=0时,此时R=0,p的下一个移动位置为p=1,也在R=0的右边

    在这种情况下,采用普遍的解法,将移动的位置设为对称中心,向两边暴力扩展,同时更新回文半径数组、最右回文右边界R和最右回文右边界的对称中心

     

    情况二:下一个要移动的位置就是最右回文右边界R或是在R的左边。又可分为3种情况

    1)cL<pL。p2是p1以c为对称中心的对称点; pL是以p2为对称中心中心的回文子串的左边界;cL是 以C为对称中心的回文子串的左边界。

    这种情况下,p1的回文半径就是p2的回文半径radius[p2]

    2)cL>pL

    这种情况下,p1的回文半径就是p1到R的距离,R-p1+1

    3)cL=pL.这种情况下p1的回文半径就换药继续往外扩,但是只需要从R之后往外扩就可以了,扩了之后 更新R和C

     

    整个过程的复杂度为O(n)

     

     

    预处理

    i

    int Init(){
        int len=strlen(s);
        s_new[0]='$';//类似于设置左边界
        s_new[1]='#';
        int j=2;
        for(int i=0;i<len;i++){
            s_new[j++]=s[i];
            s_new[j++]='#';
        } 
        s_new[j]='';//这个一定不能忘
        return j;//返回s_new的长度 
    }
    View Code

     

    处理函数

    int Manacher(){
        int len=Init();//取得新字符串长度并完成向s_new的转换
        int max_len=-1;//最长回文长度
        int id;//C 左右回文右边界的对称中心 
        int mx=0;//最右回文右边界
        for(int i=1;i<len;i++){
            if(i<mx) p[i]=min(p[2*id-i]);
            else p[i]=1;
            while(s_new[i-p[i]]==s_new[i+p[i]]) p[i]++;
            if(mx<i+p[i]) {
                id=i;
                max=i+p[i];
            }
            max_len=max(max_len,p[i]-1);
        } 
        return max_len;
    } 
    View Code

     


    作者:孙建钊
    出处:http://www.cnblogs.com/sunjianzhao/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    JSON开源库API【转载】https://nlohmann.github.io/json/index.html
    ZeroMQ示例(C/C++/PHP)详解三种模式
    Makefile精髓篇【转】
    JNI数组操作
    【摘要】malloc、calloc和realloc的用法
    容器内部安装scp,拷贝到外部物理机
    关于VMware虚拟机安装镜像时黑屏的解决办法
    linux下打压缩解压
    高效载入“大”图片
    后台执行Bitmap加载
  • 原文地址:https://www.cnblogs.com/sunjianzhao/p/14544584.html
Copyright © 2020-2023  润新知