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以上就是自己总结的马拉车算法了。

  • 相关阅读:
    Azkaban的使用
    Azkaban安装
    Kafka 启动失败,报错Corrupt index found以及org.apache.kafka.common.protocol.types.SchemaException: Error reading field 'version': java.nio.BufferUnderflowException
    Kafka 消费者设置分区策略及原理
    Kafka利用Java API自定义生产者,消费者,拦截器,分区器等组件
    zookeeper群起总是有那么几个节点起不来的问题解决
    flume 启动agent报No appenders could be found for logger的解决
    Flume 的监控方式
    Flume 自定义 组件
    Source r1 has been removed due to an error during configuration java.lang.IllegalArgumentException: Required parameter bind must exist and may not be null & 端口无法连接
  • 原文地址:https://www.cnblogs.com/sykline/p/9737705.html
Copyright © 2011-2022 走看看