知识点

manacher算法可以在时间复杂度为O(n)的情况下,求出一个字符串的最长回文子串的算法。

一 . 实现步骤

① 在字符串的各个字母中间加上一个字符,使其变成奇数字符串。对于原来是偶数字符串来说,添加的字符“#”作为对称中心;原来是奇数字符串的最中间的字母为对称中心。

② 设字符串的对称中心为mid,r表示最长回文串的右端点在哪里,i 表示当前扫描到的节点,j 节点表示 i 节点关于字符串对称中心对称的位置。


模板题

洛谷 P3805 【模板】manacher 算法

题目描述

给出一个只由小写英文字符 组成的字符串 S ,求 S 中最长回文串的长度 。

字符串长度为 n。

输入格式

一行小写英文字符  组成的字符串 S。

输出格式

一个整数表示答案。

输入输出样例

输入 #1

aaa

输出 #1

3

说明/提示

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#define ll long long
using namespace std;
const int maxn=1e8+5;
char c[maxn<<1],s[maxn];
int p[maxn<<1];
int r,mid,ans=1;
int main()
{scanf("%s",s);int len=strlen(s);c[0]=c[1]='#';p[1]=1;for(int i=1;i<=len;++i){c[2*i]=s[i-1];c[2*i+1]='#';}c[(len<<1)+2]='$';//在各个字母之间加上字符进行分割for(int i=0;i<(len<<1)+2;++i){if(i<r) p[i]=min(p[(mid<<1)-i],p[mid]+mid-i);else p[i]=1;while(c[i-p[i]]==c[i+p[i]]) p[i]++;if(p[i]+i>r){r=p[i]+i;mid=i;}}for(int i=0;i<=(len<<1)+2;++i){ans=max(ans,p[i]-1);  }printf("%d",ans);    return 0;
}

相关练习

1 . 洛谷 P1659 [国家集训队]拉拉队排练

思路:由题得“连续的一段女生,有奇数个,并且他们手中的牌子所写的字母,从左到右和从右到左读起来一样,那么就被称作和谐小群体” ,说明需要找的这个字符串是回文字符串,可以使用manacher算法。又因为找寻的回文字符串的字符个数为奇数个,其实只需要在字符串首和尾部加上其他符号进行特判即可。需要注意数据范围很大,需要使用快速幂进行加速运算。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
#define re register
using namespace std;
ll int n,k;
const int maxn=1e7+5,mod=19930726;
char c[maxn],s[maxn<<1];
ll int p[maxn<<1],front[maxn];
ll int mid,r,len;
inline ll int quick_pow(ll int x,ll int y) //快速幂加速
{ll int ans=1;while(y){if(y&1){ans=(ans*x)%mod;}x=(x*x)%mod;y>>=1;}return ans;
}int main()
{scanf("%d%d",&n,&k);scanf("%s",c+1);len=n;s[0]=s[1]='#';for(re ll int i=1;i<=len;++i){s[i<<1]=c[i];s[i<<1|1]='#';}len=(len<<1)+2;s[len]='$';for(re ll int i=1;i<len;++i){if(i<r) p[i]=min(p[(mid<<1)-i],r-i);else p[i]=1;while(s[i-p[i]]==s[p[i]+i]) p[i]++; //这里要注意是i-p[i]!!!if(p[i]+i>r){r=p[i]+i;mid=i;}if((p[i]-1)&1) front[p[i]-1]++; //用桶标记有几个奇数字符串}ll int sum=0,res=1;if(n%2==0) n--; //只需统计奇数的字符串for(re ll int i=n;i>=1;i-=2){sum+=front[i]; //统计有几个和谐小群体if(sum<=k){res=(res*quick_pow(i,sum))%mod; //记录前k个和谐小群体的女生个数的乘积k-=sum;   }else{res=(res*quick_pow(i,k))%mod;    break;}}if(sum<k) res=-1; //最后的总数也不能超过k,标记为-1printf("%lld",res);return 0;
}

2 . 洛谷 P4555 [国家集训队]最长双回文串

思路:(待填坑)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1e6+5;
char c[maxn<<1],s[maxn<<1];
int p[maxn<<1],len=0,r,mid,len1[maxn<<1],len2[maxn<<1];
//len1[i]表示以i开头的最长回文串的长度
//len2[i]表示以i结尾的最长回文串的长度
int main()
{scanf("%s",c+1);len=strlen(c+1);s[0]=s[1]='#';for(int i=1;i<=len;++i){s[i<<1]=c[i];s[i<<1|1]='#';}len=(len<<1)+2;s[len]='$';for(int i=1;i<len;++i){if(i<r) p[i]=min(p[(mid<<1)-i],p[mid]+mid-i);else p[i]=1;while(s[i-p[i]] == s[i+p[i]]) p[i]++;if(p[i]+i>r) {mid=i;r=p[i]+i;}len1[i-p[i]+1]=max(len1[i-p[i]+1],p[i]-1); //求出以i开头的饱和回文串的最大长度len2[i+p[i]-1]=max(len2[i+p[i]-1],p[i]-1); //求出以i结尾的饱和回文串的最大长度}//求出以i开头的饱和与不饱和回文串的最大长度for(int i=3;i<len;i+=2){len1[i]=max(len1[i],len1[i-2]-2); }//求出以i开头的饱和与不饱和回文串的最大长度for(int i=len-1;i>=3;i-=2){len2[i]=max(len2[i],len2[i+2]-2);}int Max=0;for(int i=3;i<=len;i+=2){if(len1[i]&&len2[i]) //在同一节点能保证两个子串都是回文串且总长度最长Max=max(Max,len1[i]+len2[i]);}printf("%d",Max);return 0;
}

(待填坑)【字符串】manacher(马拉车)算法相关推荐

  1. 【算法】Manacher(马拉车)算法

    原jekyll 2019-09-07 Manacher's Alogrithm,中文名叫马拉车算法,是一位叫Manacher的人在1975年提出的一种算法,解决的问题是求最长回文子串,算法的神奇之处就 ...

  2. 最长回文字符串(马拉车算法)

     Manacher算法 算法总结第三弹 manacher算法,前面讲了两个字符串相算法--kmp和拓展kmp,这次来还是来总结一个字符串算法,manacher算法,我习惯叫他 "马拉车& ...

  3. Manacher马拉车算法求最长回文子串

    终于把马拉车算法搞明白了!赶紧记录一下. 这个算法用于查找一个字符串的最长回文子串 马拉车算法依次给数组p[i]赋值,马拉车算法的本质就是在每次给数组p[i] 赋值时尝试进行偷懒 例如,当要给p[6] ...

  4. Manacher(马拉车)算法—简略讲解

    这是一篇菜鸡的算法小笔记!希望你喜欢! 前言 马拉车算法是用来查找一个字符串的最长回文子串的线性方法,是一个叫 Manacher 的人在 1975 年发明的,这个方法的最大贡献是在于将时间复杂度提升到 ...

  5. leetcode-回文字符串(马拉车算法模板)

    马拉车算法 由于看了一个巨巨的博客深受启发.所以不再赘述. 巨巨的博客 leetcode-最长回文字符串: 给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000. 示 ...

  6. (manacher)马拉车算法专题题目

    manacher算法用来求解回文串问题,时间复杂度为O(n). 不懂的先可以去练习下模板板子题,求最长回文串 传送门P3501 [POI2010]ANT-Antisymmetry 这一题他给的是一个新 ...

  7. Manacher (马拉车)算法

    Manacher于1975年发现了一种线性时间算法,可以在列出给定字符串中从任意位置开 始的所有回文子串.同样的算法也可以在任意位置查找全部极大回文子串,并且时间复杂 度是线性的.那他是怎样实现的呢, ...

  8. 什么是Manacher(马拉车)算法-java代码实现

    截止到目前我已经写了 500多道算法题,其中部分已经整理成了pdf文档,目前总共有1000多页(并且还会不断的增加),大家可以免费下载 下载链接:https://pan.baidu.com/s/1hj ...

  9. manacher马拉车算法

    算法讲解 算法讲解1 #include <iostream> #define maxn 10e+6; using namespace std; char s[maxn],str[maxn* ...

  10. Manacher(马拉车算法)

    对应letecode链接: https://leetcode-cn.com/problems/longest-palindromic-substring/ 题目描述: 给你一个字符串 s,找到 s 中 ...

最新文章

  1. java 事件cancel_ACTION_CANCEL事件和事件回传
  2. 另类的 高版本数据库 转换到 低版本数据库
  3. exc读入到matlab,matlab外部程序接口-excel
  4. Vue3---安装Element-Plus组件库
  5. cesium 局部加载_cesium自定义气泡窗口infoWindow后续优化篇 - GIS之家
  6. Deep_Rank,经典ctr系列预估模型复现框架
  7. 信息安全“拷问”智慧城市建设 如何解决?
  8. getch和getchar的区别
  9. 联想 m73 黑苹果 软路由 esxi AIO
  10. 人脸识别数据集之MS-Celeb-1M
  11. 每秒浮点运算次数FLOPS
  12. mtk平台dump系统分区
  13. Qt 的 linuxFB XCB KMS XCB Wayland
  14. pycharm引用pyd文件
  15. 捋一捋二分类和多分类中的交叉熵损失函数
  16. Android--设置显示大小导致APP crash
  17. cql oracle,执行简单的CQL操作
  18. word文档中插入图片显示不全解决办法
  19. matlab用雅可比(Jacobi)迭代法求解方程组
  20. ArcGIS for IOS 添加多个覆盖物,并设置点击覆盖物触发委托

热门文章

  1. php外翻截骨术,楔形截骨术与V形截骨术治疗拇外翻效果相似
  2. 七个初学者必下载的Python编程器
  3. 1.1 机器学习和深度学习综述
  4. toString().trim()是什么意思
  5. 机器视觉光源选型总结---颜色选择
  6. vue axios 下载zip 解压报错 responseType blob arraybuffer
  7. [唐诗]寻西山隐者不遇-丘为
  8. LM2576 开关电源使用介绍
  9. 智能温度系统(C51+DS18B20温度传感器+LM016L显示屏)
  10. 凉宫春日的忧郁第一章