一、模板

算法解析:http://www.felix021.com/blog/read.php?2040

  1. *主要用来解决一个字符串中最长回文串的长度,在On)时间内,线性复杂度下,求出以每个字符串为中心的最长回文,奇数回文跟偶数回文一起考虑了
  2. S $ # # # # # # # # #
  3. P
  4.  
  5. 最后所求的值就是max(P[i]-)
  6.  
  7. //输入,并处理得到字符串s,s[0]=$
  8. void getp()
  9. {
  10. int p[], mx = , id = ;
  11. memset(p, , sizeof(p));
  12. for (i = ; s[i] != '\0'; i++)
  13. {
  14. p[i] = mx>i ? min(p[*id-i], mx-i) : ;
  15. while (s[i + p[i]] == s[i - p[i]]) p[i]++;
  16. if (i + p[i] > mx)
  17. {
  18. mx = i + p[i];
  19. id = i;
  20. }
  21. }
  22. }

二、题目

1、【HDU 4513】吉哥系列故事――完美队形II

题意:输入n(1 <= n <= 100000)个人的身高hi(50 <= hi <= 250),从这些人中连续挑出k个人,这k个人【身高是左右对称的,如果是k是奇数,那么中间那个人的身高任意】&&【从左到中间那个人,身高需保证不下降,如果用H表示新队形的高度,则H[1] <= H[2] <= H[3] .... <= H[mid]】,求k的最大值。

解题思路:一般的manacher添加的是’#’,但是本题左半边的身高不递减,所以添加的应该是(h[i]+h[i+1])/2,注意细节。处理后的第奇数个身高是添加上去的,第偶数个身高是一开始输入的,当i-p[i]是奇数时,无论hh[i-p[i]]与hh[i+p[i]]是否相等,p[i]都应该+1。

比如:h[] = 80 60 70 60 90 50 ==> hh[] = -1 65  70  65  65  75  70  65【有颜色的是原串】,以70为中心时,p[6]=4而不是3

  1. #include <iostream>
  2. #include <algorithm>
  3. #include <cstdio>
  4. #include <cstring>
  5. #include <string>
  6. using namespace std;
  7. const int N=*1e5+;
  8. int h[N], hh[N];
  9. int t, n;
  10. int p[N], lenhh;
  11. void getp()
  12. {
  13. int mx = , id = ;
  14. memset(p, , sizeof(p));
  15. for (int i = ; i<lenhh; i++)
  16. {
  17. p[i] = mx>i ? min(p[*id-i], mx-i) : ;
  18. while(hh[i + p[i]] == hh[i - p[i]] && hh[i-p[i]]<=hh[i-p[i]+]) p[i]++;
  19. if((i-p[i])%) p[i]++;
  20. if (i + p[i] > mx)
  21. {
  22. mx = i + p[i];
  23. id = i;
  24. }
  25. }
  26. }
  27. int main(){
  28. scanf("%d", &t);
  29. while(t--){
  30. scanf("%d", &n);
  31. for(int i=; i<=n; i++){
  32. scanf("%d", &h[i]);
  33. }
  34. h[]=h[n], h[n+]=h[];
  35. lenhh=;
  36. hh[]=(h[]+h[])/, hh[]=-;
  37. for(int i=; i<=n; i++){
  38. hh[lenhh++]=h[i];
  39. hh[lenhh++]=(h[i]+h[i+])/;
  40. }
  41. // for(int i=0; i<lenhh; i++) cout<<hh[i]<<" ";
  42. // cout<<endl;
  43. getp();
  44. int maxn=;
  45. // for(int i=0; i<lenhh; i++) cout<<p[i]<<" ";
  46. // cout<<endl;
  47. for(int i=; i<lenhh; i++) maxn = max(maxn, p[i]-);
  48. printf("%d\n", maxn);
  49. }
  50. return ;
  51. }

2、【HDU 3948】The Number of Palindromes(manacher +建图 || )

题意:输入一个字符串(len<=1e5),求这个字符串中不同的回文子串的个数,如:【输入aaaa,有四个不同的回文子串,a、aa、aaa、aaaa】

解题思路:先用计算字符串的hash值,manacher算法求出p[],枚举每一个中心点,从可能的最长回文串的两端逐渐向里判断是否出现过,如果长的出现过了,那短的也一定出现过。判断这个字符串是否出现过目前一共有两种方法:【最后的点的总数不会超过3*1e5的,那就将每一个hash值都对mod(mod=3*1e5+10)取余,建图,hash值%mod后相等的利用head连成一个图】&&【这一种方式就是比较费时但也比较直接的,直接用map判断这个hash值是不是出现过】

Get新技能:将判断字符串是否出现过转化为判断hash值是不是出现过,同时建图判断hash值是否出现过。

manacher+建图

  1. #include <iostream>
  2. #include <algorithm>
  3. #include <cstdio>
  4. #include <cstring>
  5. #include <string>
  6. #include <map>
  7. using namespace std;
  8.  
  9. #define ull unsigned long long
  10. #define ll __int64
  11.  
  12. const int N = 1e5+;
  13. const ull bas = ;
  14. ull has[N], base[N];
  15. char s[N], ss[*N];
  16. int lenss, p[*N];
  17.  
  18. struct hash_map{
  19. const static int mod=*N+;//一个静态的、值不能被改变的整型常量
  20. int idx, head[mod];
  21.  
  22. struct hash_tables{
  23. int next;
  24. ull key;
  25. }ele[*N];
  26.  
  27. void init(){
  28. idx = ;
  29. memset(head, 0xff, sizeof(head));//初始化为-1
  30. }
  31.  
  32. void clear(){// clear的效率要高于init的效率,后期的用以替换init
  33. for(int i=; i<idx; i++){
  34. head[ele[i].key%mod] = -;
  35. }
  36. idx = ;
  37. }
  38.  
  39. void insert(ull x){
  40. int tmp = x%mod;
  41. ele[idx].key = x;
  42. ele[idx].next = head[tmp];
  43. head[tmp] = idx++;
  44. }
  45.  
  46. bool find(ull x){
  47. int hashcode = x%mod;
  48. for(int i=head[hashcode]; i!=-; i=ele[i].next){
  49. if(ele[i].key == x) return true;
  50. }
  51. return false;
  52. }
  53. }hashi; // 将hash表的实现封装成一个类
  54.  
  55. ll ans;
  56.  
  57. void manacher(){
  58. int mx = , id = ;
  59. memset(p, , sizeof(p));
  60. for (int i = ; i<lenss; i++)
  61. {
  62. p[i] = mx>i ? min(p[*id-i], mx-i) : ;
  63. while (ss[i + p[i]] == ss[i - p[i]]) p[i]++;
  64. if (i + p[i] > mx)
  65. {
  66. mx = i + p[i];
  67. id = i;
  68. }
  69. }
  70. }
  71. void init(){
  72. ss[] = '$', ss[] = '#';
  73. lenss = , has[]=;
  74. int len=strlen(s);
  75. for(int i=; i<len; i++){
  76. has[i+] = has[i]*bas+s[i]-'a'+;
  77. ss[lenss++] = s[i];
  78. ss[lenss++] = '#';
  79. }
  80. ss[lenss]='\0';
  81. manacher();
  82. }
  83. int begn, ed;
  84. void find(int id, int dis){
  85. begn=id-dis+, ed=id+dis-;
  86. if(begn%==) begn++, ed--;
  87. while(begn<=ed){
  88. ull k = has[ed/] - has[begn/-]*base[ed/-begn/+];
  89. if(!hashi.find(k)){
  90. hashi.insert(k);
  91. ans++;
  92. }
  93. else break;
  94. begn+=, ed-=;
  95. }
  96. }
  97. int main(){
  98. int t, cas=;
  99. scanf("%d", &t);
  100. hashi.init();
  101. base[] = ;
  102. for(int i=; i<N; i++) base[i] = base[i-]*bas;
  103.  
  104. while(t--){
  105. hashi.clear();
  106. scanf("%s", s);
  107. init();
  108.  
  109. ans = ;
  110. for(int i=; i<lenss; i++){
  111. find(i, p[i]);
  112. }
  113. printf("Case #%d: %I64d\n", cas++, ans);
  114. }
  115. return ;
  116. }

manacher+map

  1. #include <iostream>
  2. #include <algorithm>
  3. #include <cstdio>
  4. #include <cstring>
  5. #include <string>
  6. #include <map>
  7. using namespace std;
  8.  
  9. #define ull unsigned long long
  10.  
  11. const int N = 1e5+;
  12. const ull bas = ;
  13. ull has[N], base[N];
  14. char s[N], ss[*N];
  15. int lenss, p[*N];
  16. map<ull, int>mp;
  17.  
  18. int ans;
  19.  
  20. void manacher(){
  21. int mx = , id = ;
  22. memset(p, , sizeof(p));
  23. for (int i = ; ss[i] != '\0'; i++)
  24. {
  25. p[i] = mx>i ? min(p[*id-i], mx-i) : ;
  26. while (ss[i + p[i]] == ss[i - p[i]]) p[i]++;
  27. if (i + p[i] > mx)
  28. {
  29. mx = i + p[i];
  30. id = i;
  31. }
  32. }
  33. }
  34. void init(){
  35. ss[] = '$', ss[] = '#';
  36. lenss = , has[]=;
  37. int len = strlen(s);
  38. for(int i=; i<len; i++){
  39. has[i+] = has[i]*bas+s[i]-'a'+;
  40. ss[lenss++] = s[i];
  41. ss[lenss++] = '#';
  42. }
  43. ss[lenss] = '\0';
  44. manacher();
  45. }
  46. int begn, ed;
  47. void find(int id, int dis){
  48. begn=id-dis+, ed=id+dis-;
  49. if(begn%==) begn++, ed--;
  50. while(begn<=ed){
  51. ull k = has[ed/] - has[begn/-]*base[ed/-begn/+];
  52. if(!mp[k]){
  53. mp[k] = ;
  54. ans++;
  55. }
  56. else break;
  57. begn+=, ed-=;
  58. }
  59. }
  60. int main(){
  61. int t, cas=;
  62. scanf("%d", &t);
  63.  
  64. base[] = ;
  65. for(int i=; i<N; i++) base[i] = base[i-]*bas;
  66.  
  67. while(t--){
  68. scanf("%s", s);
  69. init();
  70.  
  71. ans = , mp.clear();
  72. for(int i=; i<lenss; i++){
  73. find(i, p[i]);
  74. }
  75. printf("Case #%d: %d\n", cas++, ans);
  76. }
  77. return ;
  78. }

manacher算法专题的更多相关文章

  1. HDU3068 回文串 Manacher算法

    好久没有刷题了,虽然参加过ACM,但是始终没有融会贯通,没有学个彻底.我干啥都是半吊子,一瓶子不满半瓶子晃荡. 就连简单的Manacher算法我也没有刷过,常常为岁月蹉跎而感到后悔. 问题描述 给定一 ...

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

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

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

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

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

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

  5. LeetCode 5 Longest Palindromic Substring manacher算法,最长回文子序列,string.substr(start,len) 难度:2

    https://leetcode.com/problems/longest-palindromic-substring/ manacher算法相关:http://blog.csdn.net/ywhor ...

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

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

  7. 【转】最长回文子串的O(n)的Manacher算法

    Manacher算法 首先:大家都知道什么叫回文串吧,这个算法要解决的就是一个字符串中最长的回文子串有多长.这个算法可以在O(n)的时间复杂度内既线性时间复杂度的情况下,求出以每个字符为中心的最长回文 ...

  8. Manacher算法

    Manacher算法是求回文串最高效的算法,能在线性时间内求出以每一个字符为中心的最长回文串.   首先,我们都能想出$O(N^2)$求出每一个字符为中心的最长回文串的算法.那么我们考虑这样一种情况. ...

  9. 字符串匹配--manacher算法模板

    manacher算法主要是处理字符串中关于回文串的问题的,它可以在 O(n) 的时间处理出以字符串中每一个字符为中心的回文串半径,由于将原字符串处理成两倍长度的新串,在每两个字符之间加入一个特定的特殊 ...

随机推荐

  1. Linux初识二

    1. Linux上常用的文件管理命令及使用 (1) CP命令:复制文件或文件夹语法格式 cp [OPTION]... [-T] SOURCE DEST // 单源复制 cp [OPTION]... S ...

  2. 【只需3步】Linux php的安装与配置[源码安装]

    作者小波/QQ463431476欢迎转载! Linux:redhat 6/centos 6 继续上一篇笔记Apache的配置http://www.cnblogs.com/xiaobo-Linux/p/ ...

  3. VS2015+Win10 调试DirectX 报错

    安装完Win10调试程序突然在这个地方报错: #if (defined(DEBUG) || defined(_DEBUG)) deviceFlags |= D3D11_CREATE_DEVICE_DE ...

  4. JVM原理和优化

    JVM工作原理和特点主要是指操作系统装入JVM是通过jdk中Java.exe来完成,通过下面4步来完成JVM环境. 1.创建JVM装载环境和配置 2.装载JVM.dll 3.初始化JVM.dll并挂界 ...

  5. IT培训行业揭秘(三)

    关于培训班的课程是怎么设置的呢? 首先,国内也有几个水平不错的培训机构有自己课程研发体系,有自己的课程研发部门.我一直认为良心培训和黑心培训的区别就在这里,因为学生们所学的知识符不符合市场用功需求,就 ...

  6. css一些进入条

    http://www.jq22.com/jquery-info5309 http://www.jq22.com/jquery-info10964 http://www.jq22.com/jquery- ...

  7. 腾讯 auth_token

    auth_token 从cookies里取出supertoken=2881515311; function auth_token(str) { var hash = 0; for (var i = 0 ...

  8. jQuery form表单序列化为JSON对象!

    /* 来源于博客园http://www.cnblogs.com/nixil/archive/2010/12/08/1900745.html */ function paramString2obj(se ...

  9. 使用Xunit进行单元测试

    http://xunit.github.io/docs/getting-started-desktop.html 1. 新建一个类库项目 2. 通过NuGet引入xunit,Shouldly,xuni ...

  10. 将字符串中的URL 解析,获取内容

    parse_str() : parse_str("name=Bill&age=60"); echo $name."<br>";//Bill ...