博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
最长回文子串算法-- Manacher算法--O(n)
阅读量:4141 次
发布时间:2019-05-25

本文共 2323 字,大约阅读时间需要 7 分钟。

 这里,我介绍一下On)回文串处理的一种方法。Manacher算法.
原文地址:

    其实原文说得是比较清楚的,只是英文的,我这里写一份中文的吧。
    首先:大家都知道什么叫回文串吧,这个算法要解决的就是一个字符串中最长的回文子串有多长。这个算法可以在On)的时间复杂度内既线性时间复杂度的情况下,求出以每个字符为中心的最长回文有多长,
    这个算法有一个很巧妙的地方,它把奇数的回文串和偶数的回文串统一起来考虑了。这一点一直是在做回文串问题中时比较烦的地方。这个算法还有一个很好的地方就是充分利用了字符匹配的特殊性,避免了大量不必要的重复匹配。
    算法大致过程是这样。先在每两个相邻字符中间插入一个分隔符,当然这个分隔符要在原串中没有出现过。一般可以用‘#’分隔。这样就非常巧妙的将奇数长度回文串与偶数长度回文串统一起来考虑了(见下面的一个例子,回文串长度全为奇数了),然后用一个辅助数组P记录以每个字符为中心的最长回文串的信息。Pid]记录的是以字符strid]为中心的最长回文串,当以strid]为第一个字符,这个最长回文串向右延伸了Pid]个字符。
    原串:    w aa bwsw f d
    新串:   # w# a # a # b# w # s # w # f # d #
辅助数组P:  1 2 1 2 3 2 1 2 1 2 1 4 1 2 1 2 1 2 1
    这里有一个很好的性质,Pid-1就是该回文子串在原串中的长度(包括‘#’)。如果这里不是特别清楚,可以自己拿出纸来画一画,自己体会体会。当然这里可能每个人写法不尽相同,不过我想大致思路应该是一样的吧。
    好,我们继续。现在的关键问题就在于怎么在On)时间复杂度内求出P数组了。只要把这个P数组求出来,最长回文子串就可以直接扫一遍得出来了。
    由于这个算法是线性从前往后扫的。那么当我们准备求Pi]的时候,i以前的Pj]我们是已经得到了的。我们用mx记在i之前的回文串中,延伸至最右端的位置。同时用id这个变量记下取得这个最优mx时的id值。(注:为了防止字符比较的时候越界,我在这个加了‘#’的字符串之前还加了另一个特殊字符‘$’,故我的新串下标是从1开始的)
好,到这里,我们可以先贴一份代码了。


  1. void pk()
    {

        int i;
        int mx = 0;
        int id;
        for(i=1; i<n; i++)
        {

            if( mx > i )
                p[i] = MIN( p[2*id-i], mx-i );        
            else
                p[i] = 1;
            for(; str[i+p[i]] == str[i-p[i]]; p[i]++)
                ;
            if( p[i] + i > mx )
            {

                mx = p[i] + i;
                id = i;
            }
        }
    }

   代码是不是很短啊,而且相当好写。很方便吧,还记得我上面说的这个算法避免了很多不必要的重复匹配吧。这是什么意思呢,其实这就是一句代码。

if
(
 mx 
>
 i
)
    p
[
i
]
=
MIN
(
 p
[
2
*
id
-
i
],
 mx
-
i
);

就是当前面比较的最远长度mx>i的时候,Pi]有一个最小值。这个算法的核心思想就在这里,为什么P数组满足这样一个性质呢?
   (下面的部分为图片形式)




    看完这个算法,你有可能会觉得这种算法在哪会用到呢?其实回文串后缀数组也可以做。只是复杂度是On log n)的,而且一般情况下也不会刻意去卡一个log n的算法。可正好hdu就有这么一题,你用后缀数组写怎么都得T(当然应该是我写得太烂了)。不信的话大家也可以去试试这题。
        
    另外,顺便附一份AC代码。

        

更正后代码:

 
[cpp] 
  1. #include<vector>  
  2. #include<iostream>  
  3. using namespace std;  
  4.   
  5. const int N=300010;  
  6. int n, p[N];  
  7. char s[N], str[N];  
  8.   
  9. #define _min(x, y) ((x)<(y)?(x):(y))  
  10.   
  11. void kp()  
  12. {  
  13.     int i;  
  14.     int mx = 0;  
  15.     int id;  
  16.     for(i=n; str[i]!=0; i++)  
  17.         str[i] = 0; //没有这一句有问题。。就过不了ural1297,比如数据:ababa aba  
  18.     for(i=1; i<n; i++)  
  19.     {  
  20.         if( mx > i )  
  21.             p[i] = _min( p[2*id-i], p[id]+id-i );  
  22.         else  
  23.             p[i] = 1;  
  24.         for(; str[i+p[i]] == str[i-p[i]]; p[i]++)  
  25.             ;  
  26.         if( p[i] + i > mx )  
  27.         {  
  28.             mx = p[i] + i;  
  29.             id = i;  
  30.         }  
  31.     }  
  32. }  
  33.   
  34. void init()  
  35. {  
  36.     int i, j, k;  
  37.     str[0] = '$';  
  38.     str[1] = '#';  
  39.     for(i=0; i<n; i++)  
  40.     {  
  41.         str[i*2+2] = s[i];  
  42.         str[i*2+3] = '#';  
  43.     }  
  44.     n = n*2+2;  
  45.     s[n] = 0;  
  46. }  
  47.   
  48. int main()  
  49. {  
  50.     int i, ans;  
  51.     while(scanf("%s", s)!=EOF)  
  52.     {  
  53.         n = strlen(s);  
  54.         init();  
  55.         kp();  
  56.         ans = 0;  
  57.         for(i=0; i<n; i++)  
  58.             if(p[i]>ans)  
  59.                 ans = p[i];  
  60.         printf("%d\n", ans-1);  
  61.     }  
  62.     return 0;  
  63. }  
http://blog.csdn.net/ggggiqnypgjg/article/details/6645824
你可能感兴趣的文章
Kubernetes集群搭建之CNI-Flanneld部署篇
查看>>
k8s web终端连接工具
查看>>
手绘VS码绘(一):静态图绘制(码绘使用P5.js)
查看>>
手绘VS码绘(二):动态图绘制(码绘使用Processing)
查看>>
基于P5.js的“绘画系统”
查看>>
《达芬奇的人生密码》观后感
查看>>
论文翻译:《一个包容性设计的具体例子:聋人导向可访问性》
查看>>
基于“分形”编写的交互应用
查看>>
《融入动画技术的交互应用》主题博文推荐
查看>>
链睿和家乐福合作推出下一代零售业隐私保护技术
查看>>
Unifrax宣布新建SiFAB™生产线
查看>>
艾默生纪念谷轮™在空调和制冷领域的百年创新成就
查看>>
NEXO代币持有者获得20,428,359.89美元股息
查看>>
Piper Sandler为EverArc收购Perimeter Solutions提供咨询服务
查看>>
RMRK筹集600万美元,用于在Polkadot上建立先进的NFT系统标准
查看>>
JavaSE_day14 集合中的Map集合_键值映射关系
查看>>
异常 Java学习Day_15
查看>>
Mysql初始化的命令
查看>>
MySQL关键字的些许问题
查看>>
浅谈HTML
查看>>