Manacher算法

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

  1. void pk()
  2. {
  3. int i;
  4. int mx = ;
  5. int id;
  6. for(i=; i<n; i++)
  7. {
  8. if( mx > i )
  9. p[i] = MIN( p[*id-i], mx-i );
  10. else
  11. p[i] = ;
  12. for(; str[i+p[i]] == str[i-p[i]]; p[i]++)
  13. ;
  14. if( p[i] + i > mx )
  15. {
  16. mx = p[i] + i;
  17. id = i;
  18. }
  19. }
  20. }
代码是不是很短啊,而且相当好写。很方便吧,还记得我上面说的这个算法避免了很多不必要的重复匹配吧。这是什么意思呢,其实这就是一句代码。
 
if( mx > i )
    p[i] = MIN( p[2*id-i], mx-i );
 
就是当前面比较的最远长度mx>i的时候,P[i]有一个最小值。这个算法的核心思想就在这里,为什么P数组满足这样一个性质呢?
   (下面的部分为图片形式)
 
 
    看完这个算法,你有可能会觉得这种算法在哪会用到呢?其实回文串后缀数组也可以做。只是复杂度是O(n log n)的,而且一般情况下也不会刻意去卡一个log n的算法。可正好hdu就有这么一题,你用后缀数组写怎么都得T(当然应该是我写得太烂了)。不信的话大家也可以去试试这题。

http://acm.hdu.edu.cn/showproblem.php?pid=3068
另外,顺便附一份AC代码。

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <cmath>
  5. #include <algorithm>
  6. using namespace std;
  7. #define N 230017
  8.  
  9. char ss[*N+];
  10. int p[N],n;
  11. char s[N];
  12.  
  13. void pk()
  14. {
  15. int i;
  16. int mx = ,id;
  17. p[] = ;
  18. for(i=;i<n;i++)
  19. {
  20. if(mx > i)
  21. p[i] = min(p[*id-i],mx-i);
  22. else
  23. p[i] = ;
  24. while(ss[i+p[i]] == ss[i-p[i]])
  25. p[i]++;
  26. if(p[i] + i > mx)
  27. {
  28. mx = p[i]+i;
  29. id = i;
  30. }
  31. }
  32. }
  33.  
  34. int main()
  35. {
  36. int t,i;
  37. while(scanf("%s",s)!=EOF)
  38. {
  39. n = strlen(s);
  40. ss[] = '@';
  41. ss[] = '#';
  42. for(i=;i<n;i++)
  43. {
  44. ss[*i+] = s[i];
  45. ss[*i+] = '#';
  46. }
  47. n = *n+;
  48. ss[n] = ;
  49. pk();
  50. int maxi = ;
  51. for(i=;i<n;i++)
  52. maxi = max(maxi,p[i]);
  53. printf("%d\n",maxi-);
  54. }
  55. return ;
  56. }

【转】最长回文子串的O(n)的Manacher算法的更多相关文章

  1. Leetcode(5)-最长回文子串(包含动态规划以及Manacher算法)

    给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为1000. 示例 1: 输入: "babad" 输出: "bab" 注意: &quo ...

  2. 最长回文子串-LeetCode 5 Longest Palindromic Substring

    题目描述 Given a string S, find the longest palindromic substring in S. You may assume that the maximum ...

  3. 最长回文子串(Longest Palindromic Substring)

    这算是一道经典的题目了,最长回文子串问题是在一个字符串中求得满足回文子串条件的最长的那一个.常见的解题方法有三种: (1)暴力枚举法,以每个元素为中心同时向左和向右出发,复杂度O(n^2): (2)动 ...

  4. lintcode最长回文子串(Manacher算法)

    题目来自lintcode, 链接:http://www.lintcode.com/zh-cn/problem/longest-palindromic-substring/ 最长回文子串 给出一个字符串 ...

  5. 1089 最长回文子串 V2(Manacher算法)

    1089 最长回文子串 V2(Manacher算法) 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 回文串是指aba.abba.cccbccc.aaaa ...

  6. 51nod1089(最长回文子串之manacher算法)

    题目链接: https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1089 题意:中文题诶~ 思路: 我前面做的那道回文子串的题 ...

  7. 求最长回文子串:Manacher算法

    主要学习自:http://articles.leetcode.com/2011/11/longest-palindromic-substring-part-ii.html 问题描述:回文字符串就是左右 ...

  8. [译+改]最长回文子串(Longest Palindromic Substring) Part II

    [译+改]最长回文子串(Longest Palindromic Substring) Part II 原文链接在http://leetcode.com/2011/11/longest-palindro ...

  9. [译]最长回文子串(Longest Palindromic Substring) Part I

    [译]最长回文子串(Longest Palindromic Substring) Part I 英文原文链接在(http://leetcode.com/2011/11/longest-palindro ...

随机推荐

  1. 免费素材:包含 250+ 组件的 DO UI Kit

    DO UI kit 现在可以免费用于 Photoshop 和 Sketch 了.它有超过130个屏幕,10个完整的主题以及250+的组件混合以创造惊人的应用.他们都是再混合和视网膜.最重要的是他们看起 ...

  2. Web Audio API_基本概念

    Audio Context 音频的工作环境.类比做化学实验,Audio Context 就是为我们提供各种仪器和材料的实验室(严格地来说制造这些仪器材料的方法和工具也一并提供了).通常来说做实验一间实 ...

  3. Eclipse开发STM32出现找不到函数的情况的解决方法

    问题表现: 在明明引用了头文件的情况下,出现“undefined reference to  `…'”的情况,例如下图: 解决方法: 在左边的数据目录定位到“system\src\stm32f0-st ...

  4. Python学习02 列表 List

    Python学习02 列表 List Python列表 List Python中的列表(List)用逗号分隔,方括号包围(comma-separated values (items) between ...

  5. 一个UILabel不同部分显示不同颜色

    我们直接来看效果图吧: 需求:就是表格cell里面的状态Label,前面的"状态:"是黑色,后面的状态值是红色,他们在同一个Label上,怎么做呢? 解答:真的是会者不难,难者不会 ...

  6. iOS中View生命周期与布局

    生命周期 说到view的生命周期一般都是指视图控制器的view生命周期. view的创建:loadView 视图控制器(UIViewController)及其子类,无论是手写代码还是storyboar ...

  7. python 判断学期与学年

    9,10,11,12,1 第一学期 2,3,4,5,6,7 第二学期 其中8月份放假,暂且放入第一学期.因为大部分学校都选在8月底开学 import datetime def getXNandXQ() ...

  8. ASP.NET中常用的几个李天平开源公共类LTP.Common,Maticsoft.DBUtility,LtpPageControl

    ASP.NET中常用的几个开源公共类: LTP.Common.dll: 通用函数类库     源码下载Maticsoft.DBUtility.dll 数据访问类库组件     源码下载LtpPageC ...

  9. AEAI DP开发平台精要

    1 背景概述 相信很多了解数通畅联软件的人对AEAI DP应用开发平台并不陌生,笔者在入职第一天就开始接触AEAI DP,使用AEAI DP开发过AEAI WM.AEAI CRM以及中国XXXX管理系 ...

  10. 15、安全工程师要阅读的书籍 - IT软件人员书籍系列文章

    信息安全工程师是一个比较新兴的角色.在2016年今年的下半年软考就将安全工程师纳入了考试科目,说明国家对安全工程师的需求还是不错的.安全工程师包括硬件和软件两块内容吧.这里描述的安全工程师主要是针对软 ...