Manacher算法--O(n)回文子串算法

转载 2011年07月30日 00:41:20
On)回文子串算法

注:转载的这篇文章,我发现下面那个源代码有点bug。。。在下一篇博客中改正了。。

 

    这里,我介绍一下On)回文串处理的一种方法。Manacher算法.
原文地址:
http://zhuhongcheng.wordpress.com/2009/08/02/a-simple-linear-time-algorithm-for-finding-longest-palindrome-sub-string/
    其实原文说得是比较清楚的,只是英文的,我这里写一份中文的吧。
    首先:大家都知道什么叫回文串吧,这个算法要解决的就是一个字符串中最长的回文子串有多长。这个算法可以在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(当然应该是我写得太烂了)。不信的话大家也可以去试试这题。
        http://acm.hdu.edu.cn/showproblem.php?pid=3068
    另外,顺便附一份AC代码。
        http://acm.hust.edu.cn:8080/judge/problem/viewSource.action?id=140283

Manacher算法处理字符串回文

Manacher算法 分类: 数据结构&算法2013-06-14 12:55 33人阅读 评论(0) 收藏 举报 算法Manacher回文 目录(?)[+] ...
  • pi9nc
  • pi9nc
  • 2013年07月05日 13:42
  • 15961

Manacher算法总结

Manacher算法 算法总结第三弹 manacher算法,前面讲了两个字符串相算法——kmp和拓展kmp,这次来还是来总结一个字符串算法,manacher算法,我习惯叫他 “马拉车”算法。 相对于前...
  • dyx404514
  • dyx404514
  • 2014年12月21日 16:10
  • 12421

[算法系列之七]Manacher算法之最大回文子串

回文串定义:“回文串”是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串。 回文子串,顾名思义,即字符串中满足回文性质的子串。 经常有一些题目围绕回文子串进行讨论,比如 ...
  • SunnyYoona
  • SunnyYoona
  • 2014年10月23日 09:45
  • 3171

[转]回文串判断算法——Manacher算法

以下文字转自 ddyyxx博客: Manacher算法总结Manacher算法总结算法总结第三弹 manacher算法,前面讲了两个字符串相算法——kmp和拓展kmp,这次来还是来总结一个字符串算法...
  • hk2291976
  • hk2291976
  • 2016年04月09日 22:06
  • 4325

回文字符串小结(回文串判定+最长回文子序列)

定义:“回文串”是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串。 回文串判定 例1:hdu2029 题意:请写一个程序判断读入的字符串是否是“回文”。 ...
  • qq_15714857
  • qq_15714857
  • 2015年05月29日 14:15
  • 1418

算法竞赛入门经典 例题 3-4 回文串

输入一个字符串,求出其中最长的回文子串。子串的含义是:在原串中连续出现的字符串片段。回文的含义是:正着看和倒着看相同。如abba和yyxyy。在判断时,应该忽略所有标点符号和空格,且忽略大小写,但输出...
  • oceaniwater
  • oceaniwater
  • 2014年11月02日 17:12
  • 1551

hdu3068之manacher算法+详解

最长回文 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submi...
  • xingyeyongheng
  • xingyeyongheng
  • 2013年07月12日 14:24
  • 20074

poj 3974 Palindrome 裸的最长回文子串Mancher算法O(n)

//poj 3974 //sep9 #include using namespace std; const int MAXN=1000024; char a[MAXN],b[2*MAXN]; in...
  • sepNINE
  • sepNINE
  • 2015年10月16日 13:46
  • 266

最长回文字串(mancher算法)

POJ 3974 最长回文字串(manacher算法) 分类: 数据结构2013-09-06 14:43 490人阅读 评论(0) 收藏 举报 题意:给出一个字符串,求出最长回文字串。 思...
  • acm_BaiHuzi
  • acm_BaiHuzi
  • 2014年12月03日 21:48
  • 922

Manacher

Manacher算法总结。
  • zzkksunboy
  • zzkksunboy
  • 2017年05月21日 18:19
  • 2799
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Manacher算法--O(n)回文子串算法
举报原因:
原因补充:

(最多只允许输入30个字)