zoukankan      html  css  js  c++  java
  • manacher(马拉车)算法

    断断续续地看了两天的马拉车算法,可算是给搞明白了(贼开心),这算是自己搞懂的第一个算法了(23333333333333)这个算法照目前自己的理解来看,貌似就只能求个字符串中的回文串(接触这个算法是要求最长的回文串),虽然应用的范围有点少,但还是要学习滴,不然遇到类似的题目就gg了。

    可以在线性时间内求得答案,时间复杂度为O(n)。

    1、回文串的个数是可奇可偶的,碰上奇数的回文串还可以,如果是偶数的回文串没有着脚点,那就很恼人了。所以马拉车算法会对字符串进行预先处理,然后再求最长的回文串。首先用字符串中没有出现过的字符来表示串中每个元素的间隔,而为了防止在访问时出现越界情况,需要在串首和串尾再加上额外的特殊字符。

    例如:原串为ababab;处理完之后就是$#a#b#a#b#a#b#$;  其实对于最后一个$,也可以不加,因为字符串的最后一个字符是‘\0’就相当于一个特殊字符了。

       //设t为将要进行预处理的字符串,则处理实现如下
        string t="@#";
        for(int i=0;i<str.size();i++)
        {
            t=t+str[i];
            t=t+"#";
        }

    2、接下来就是在新串中找以每一个字符为中心的回文串就可以了。manacher算法的思想就是从左到右求出以每个字符为中心的最长回文串。设能延伸到最右边的字符串的中心位置为id,该字符串最右端的位置为mx,pal数组来储存此处回文串的长度。因为回文串有对称的性质,所以后边的字符串可以通过对称来直接求得其长度(当然前边的还是需要乖乖的遍历求出来的)。

    3、对于遍历到的字符(下标设为i),一共会有三种情况;

     (1)i<=mx;

            情况如下图所示(第一次用画图的我表示已经被逼疯了emmmmm)

      

            该情况下就万事大吉了,直接把2*id-i处串的长度,复制给i就OK了。

      (2)i<=mx

            同样是这种情况但是出现i处的回文串超出了mx的情况如下图

            最右端超出了mx的范围,出现什么情况就不好说了,所以只能暴力一下,然后更新mx的大小就可以了

        (3)i>mx

            这种情况直接暴力,求此处回文串的长度即可。附上自己写的代码

    int mx=0,id=0,len=0;
        vector<int> pal(t.size(),0);
        for(int i=1;i<t.size();i++)
        {
            //pal数组存的其实是此处回文串的长度+1
            pal[i]=mx>i ? min(pal[2*id-i],mx-i):1;//此处为最关键的一处
            //当 mx>i 当然是要选一个小的来赋值,这样就可以防止超出mx了
            //然后再接着暴力枚举后边的是不是回文串,以使它的长度增加。
            //当 mx<=i时,此处的长度为1,直接进入暴力枚举它的长度
            while(t[i+pal[i]]==t[i-pal[i]] && ss.count(t[i+pal[i]]))
            {
                ++pal[i];
            }
            //最右端回文串的长度超出mx后就要进行mx和id的更新了
            if(mx < i+pal[i])
            {
                mx = i+pal[i];
                id=i;
            }
            if(len < pal[i]-1)
            {
                len=pal[i]-1;
            }
        }
    View Code

    OK以上就是自己总结的马拉车算法了。

  • 相关阅读:
    ASP.NET -- repeater控件的使用
    在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误。未找到或无法访问服务器。请验证实例名称是否正确并且 SQL Server 已配置为允许远程连接。 (provider: 命名管道提供程序, error: 40
    错误提示:在此上下文中不允许使用名称 "***"。有效表达式包括常量、 常量表达式和变量(在某些上下文中),不允许使用列名。
    mongodb 性能提高之利用索引, 待续
    工程化 经历的 4 个阶段
    把连续的字符 变成 一个
    sort 排序详解
    理解正则 的 ?! ?:
    [ 订单查询 ] 性能 高并发 : 分表 与 用户id%1024 存放表
    搭建LNMP基础框架
  • 原文地址:https://www.cnblogs.com/sykline/p/9737705.html
Copyright © 2011-2022 走看看