(待填坑)【字符串】manacher(马拉车)算法
知识点
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(马拉车)算法相关推荐
- 【算法】Manacher(马拉车)算法
原jekyll 2019-09-07 Manacher's Alogrithm,中文名叫马拉车算法,是一位叫Manacher的人在1975年提出的一种算法,解决的问题是求最长回文子串,算法的神奇之处就 ...
- 最长回文字符串(马拉车算法)
Manacher算法 算法总结第三弹 manacher算法,前面讲了两个字符串相算法--kmp和拓展kmp,这次来还是来总结一个字符串算法,manacher算法,我习惯叫他 "马拉车& ...
- Manacher马拉车算法求最长回文子串
终于把马拉车算法搞明白了!赶紧记录一下. 这个算法用于查找一个字符串的最长回文子串 马拉车算法依次给数组p[i]赋值,马拉车算法的本质就是在每次给数组p[i] 赋值时尝试进行偷懒 例如,当要给p[6] ...
- Manacher(马拉车)算法—简略讲解
这是一篇菜鸡的算法小笔记!希望你喜欢! 前言 马拉车算法是用来查找一个字符串的最长回文子串的线性方法,是一个叫 Manacher 的人在 1975 年发明的,这个方法的最大贡献是在于将时间复杂度提升到 ...
- leetcode-回文字符串(马拉车算法模板)
马拉车算法 由于看了一个巨巨的博客深受启发.所以不再赘述. 巨巨的博客 leetcode-最长回文字符串: 给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000. 示 ...
- (manacher)马拉车算法专题题目
manacher算法用来求解回文串问题,时间复杂度为O(n). 不懂的先可以去练习下模板板子题,求最长回文串 传送门P3501 [POI2010]ANT-Antisymmetry 这一题他给的是一个新 ...
- Manacher (马拉车)算法
Manacher于1975年发现了一种线性时间算法,可以在列出给定字符串中从任意位置开 始的所有回文子串.同样的算法也可以在任意位置查找全部极大回文子串,并且时间复杂 度是线性的.那他是怎样实现的呢, ...
- 什么是Manacher(马拉车)算法-java代码实现
截止到目前我已经写了 500多道算法题,其中部分已经整理成了pdf文档,目前总共有1000多页(并且还会不断的增加),大家可以免费下载 下载链接:https://pan.baidu.com/s/1hj ...
- manacher马拉车算法
算法讲解 算法讲解1 #include <iostream> #define maxn 10e+6; using namespace std; char s[maxn],str[maxn* ...
- Manacher(马拉车算法)
对应letecode链接: https://leetcode-cn.com/problems/longest-palindromic-substring/ 题目描述: 给你一个字符串 s,找到 s 中 ...
最新文章
- java 事件cancel_ACTION_CANCEL事件和事件回传
- 另类的 高版本数据库 转换到 低版本数据库
- exc读入到matlab,matlab外部程序接口-excel
- Vue3---安装Element-Plus组件库
- cesium 局部加载_cesium自定义气泡窗口infoWindow后续优化篇 - GIS之家
- Deep_Rank,经典ctr系列预估模型复现框架
- 信息安全“拷问”智慧城市建设 如何解决?
- getch和getchar的区别
- 联想 m73 黑苹果 软路由 esxi AIO
- 人脸识别数据集之MS-Celeb-1M
- 每秒浮点运算次数FLOPS
- mtk平台dump系统分区
- Qt 的 linuxFB XCB KMS XCB Wayland
- pycharm引用pyd文件
- 捋一捋二分类和多分类中的交叉熵损失函数
- Android--设置显示大小导致APP crash
- cql oracle,执行简单的CQL操作
- word文档中插入图片显示不全解决办法
- matlab用雅可比(Jacobi)迭代法求解方程组
- ArcGIS for IOS 添加多个覆盖物,并设置点击覆盖物触发委托