[最长回文字符串]manacher马拉车
manacher马拉车 https://www.luogu.com.cn/problem/P3805
闲言一下:花了一个中午终于把 manacher 给搞懂了。本文将以一个蒟蒻的身份来,来写写马拉车算法。首先请自行回顾暴力的 最长回文字符串 算法。首先我们将 通过枚举中心点,并扩展以该中心点为回文中心的回文串长度的算法称为 “中心扩展法”。manacher算法便是以“中心扩展法”为核心,利用枚举中获取的信息优化而来的。
具体地来说:
首先在解决奇偶回文字符串时,我们使用分类讨论的方法,解决了奇数和偶数的问题,但是这样未免过于麻烦,有什么可以将二者统一的方式呢?
这是处理前的字符串
具体地来说:
首先在解决奇偶回文字符串时,我们使用分类讨论的方法,解决了奇数和偶数的问题,但是这样未免过于麻烦,有什么可以将二者统一的方式呢?
这是处理前的字符串
a b b c
1 2 3 4
这是处理后的字符串
# a # b # b # c #
1 2 3 4 5 6 7 8 9
我们通过加字符的方法,注意这里不一定要是 # ,也可以是其他字符,主要目标是为了将奇偶回文字符串统一了起来。这样在处理回文字符串时,会更加的方便。(不过也容易犯一些粗心的小问题,这些问题会在文章末尾提及)。
接下来回想一下 中心扩展法 求解最长回文序列的时候。遇到这种情况时
a b a d a b a
1 2 3 4 5 6 7
当我们枚举完 以下标为 4 的点为中心时,我们可以知道 1~7 为回文序列。加上前面以下标为3的点为中心时,我们可知道 1~3 为回文序列。根据回文序列的对称性,我们可以得出 5~7 也为回文序列。但在我们使用中心扩展法时,就需要多余地去枚举以下标为3的点为中心的回文半径的长度。这大大地浪费了时间。因此我们可以从这个角度入手,优化我们的算法。
从 中心扩展法 的基础上,再根据刚刚从特殊数据的角度,我们可以想到先定义几个变量maxr,mid ,用来表示当前已知的回文序列中最右的右端点,及该回文序列的中点。为什么要记录最右的右端点呢?因为右端点越右的回文序列就越容易包括后面还未遍历的中心,这样就能尽可能的达到,通过现有信息尽可能减少多余遍历的目的了。再定义一个数组 p[i] 表示以 i 为中点的回文序列的回文半径。
具体来讲一下优化的要点,
情况一
a b b c
1 2 3 4
这是处理后的字符串
# a # b # b # c #
1 2 3 4 5 6 7 8 9
我们通过加字符的方法,注意这里不一定要是 # ,也可以是其他字符,主要目标是为了将奇偶回文字符串统一了起来。这样在处理回文字符串时,会更加的方便。(不过也容易犯一些粗心的小问题,这些问题会在文章末尾提及)。
接下来回想一下 中心扩展法 求解最长回文序列的时候。遇到这种情况时
a b a d a b a
1 2 3 4 5 6 7
当我们枚举完 以下标为 4 的点为中心时,我们可以知道 1~7 为回文序列。加上前面以下标为3的点为中心时,我们可知道 1~3 为回文序列。根据回文序列的对称性,我们可以得出 5~7 也为回文序列。但在我们使用中心扩展法时,就需要多余地去枚举以下标为3的点为中心的回文半径的长度。这大大地浪费了时间。因此我们可以从这个角度入手,优化我们的算法。
从 中心扩展法 的基础上,再根据刚刚从特殊数据的角度,我们可以想到先定义几个变量maxr,mid ,用来表示当前已知的回文序列中最右的右端点,及该回文序列的中点。为什么要记录最右的右端点呢?因为右端点越右的回文序列就越容易包括后面还未遍历的中心,这样就能尽可能的达到,通过现有信息尽可能减少多余遍历的目的了。再定义一个数组 p[i] 表示以 i 为中点的回文序列的回文半径。
具体来讲一下优化的要点,
情况一

如果是上图的这种情况,则p[i]=p[j] , j=mid-(i-mid) --> j=2*mid-i 。(回文序列的对称性)
情况二
如果是上图的这种情况,则不一定p[i]=p[j] ,因为超过ml ~ mr的部分并不满足回文序列的性质。所以只有在ml ~ mr的部分才能进入计算,因此p[i]=mr-i+1 。
重要的优化只有这些,其他的和 中心扩展法的做法大致相同。
#include<bits/stdc++.h>
using namespace std;
const int N=9*1e7;
string str="!#",c;/*为什么第一位是“!”?
为了避免程序第16行扩展时越界 */
int p[N],mid=0,mr=0,ans;
void work(){
cin>>c;
for(int i=0;c[i]>='a'&&c[i]<='z';i++){
str+=c[i];
str+='#';
}/*处理原序列*/
for(int i=1;i<str.size();i++){
if(i<=mr) p[i]=min(p[2*mid-i],mr-i+1);
/*i关于mid对称点; mid-(i-mid)——> 2*mid-i */
while(str[i-p[i]]==str[i+p[i]]) p[i]++;
//这里其实就是扩展 回文序列的 回文半径
if(i+p[i]>mr){
mid=i;
mr=i+p[i]-1;
}
if(p[i]>ans) ans=p[i];
}
cout<<ans-1;
}
int main(){
work();
return 0;
}
粗心的小问题(建议自行写完代码后查看)
1.因为要插入一堆字符,所以字符数组和其他相关数组的大小需要翻倍
[最长回文字符串]manacher马拉车的更多相关文章
- 最长回文字符串(manacher算法)
偶然看见了人家的博客发现这么一个问题,研究了一下午, 才发现其中的奥妙.Stupid. 题目描述: 回文串就是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串. ...
- 【转载】最长回文字符串(manacher算法)
原文转载自:http://blog.csdn.net/lsjseu/article/details/9990539 偶然看见了人家的博客发现这么一个问题,研究了一下午, 才发现其中的奥妙.Stupid ...
- 第5题 查找字符串中的最长回文字符串---Manacher算法
转载:https://www.felix021.com/blog/read.php?2040 首先用一个非常巧妙的方式,将所有可能的奇数/偶数长度的回文子串都转换成了奇数长度:在每个字符的两边都插入一 ...
- 最长回文子串 —— Manacher (马拉车) 算法
最长回文子串 回文串就是原串和反转字符串相同的字符串.比如 aba,acca.前一个是奇数长度的回文串,后一个是偶数长度的回文串. 最长回文子串就是一个字符串的所有子串中,是回文串且长度最长的子串. ...
- hdu3068 求一个字符串中最长回文字符串的长度 Manacher算法
最长回文 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- Manacher算法:求解最长回文字符串,时间复杂度为O(N)
原文转载自:http://blog.csdn.net/yzl_rex/article/details/7908259 回文串定义:"回文串"是一个正读和反读都一样的字符串,比如&q ...
- hdu----(3068)最长回文(manacher)
最长回文 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- 最长回文子串——manacher
最长回文子串--Manacher 算法 (原版的博主的代码都是用py写的,这里改成c++) c++ 算法 字符串处理 0. 问题定义 最长回文子串问题:给定一个字符串,求它的最长回文子串长度. 如果一 ...
- JavaScript之最长回文字符串
JavaScript经典面试题算法:最长回文字符串 下面的解题方法是通过中心扩散法的方式实现的,具体代码和注释如下(时间复杂度: O(n^2),空间复杂度:O(1)) // str字符串functio ...
- leetcode5 最长回文字符串 动态规划 Manacher法
dp 注意没有声明S不空,处理一下 o(n^2) class Solution { public: string longestPalindrome(string s) { if (s.empty() ...
随机推荐
- Android Studio中的一些常见控件
Android Studio是一款非常流行的用于开发Android应用程序的集成开发环境(IDE).它提供了许多内置控件,使开发人员可以轻松创建应用程序界面和功能.在本文中,我们将介绍Android ...
- 【vue3-element-admin】ESLint+Prettier+Stylelint+EditorConfig 约束和统一前端代码规范
前言 本文介绍 vue3-element-admin 如何通过ESLint 检测 JS/TS 代码.Prettier 格式化代码.Stylelint 检测 CSS/SCSS 代码和配置 EditorC ...
- 30-externals(拒绝某些包被打包进来)
const { resolve } = require('path') const HtmlWebpackPlugin = require('html-webpack-plugin') module. ...
- ES6 新增数组,对象,字符串的方法
1,ES6+ 新增数组方法 Array.from Array Array.from(arrayLike[, mapFn[, thisArg]]) 将类数组(伪数组)转换成数组 参数: arrayLik ...
- Amazon S3 对象存储Java API操作记录(Minio与S3 SDK两种实现)
缘起 今年(2023年) 2月的时候做了个适配Amazon S3对象存储接口的需求,由于4月份自学考试临近,一直在备考就拖着没总结记录下,开发联调过程中也出现过一些奇葩的问题,最近人刚从考试缓过来顺手 ...
- [OpenCV-Python] 17 形态学转换
文章目录 OpenCV-Python:IV OpenCV中的图像处理 17 形态学转换 17.1 腐蚀 17.2 膨胀 17.3 开运算 17.4 闭运算 17.5 形态学梯度 17.6 礼帽 17. ...
- Selenium 高亮显示操作元素
一.代码 使用 https://www.cnblogs.com/TSmagic/p/16595168.html 此篇代码即可 二.编辑 test_ys_case.py 文件 # coding=utf- ...
- pytest常用断言
如上官网所说,pytest使用python中的assert来比较实际值与预期值,实现断言功能 1 常用的断言方式 assert xxx assert a == b assert a!=b assert ...
- CentOS 8 部署 ELK 8.7真的是方便呀
之前装过一次 ELK 7.7,相比之下装 8.7可方便太多了~ CentOS版本 CentOS-8.5.2111-x86_64-dvd1 JAVA ELK会自己使用内置版本的JDK ElasticSe ...
- 2022-10-31:以下go语言代码输出什么?A:map[];B:nil;C:Panic;D:编译错误。 package main import “fmt“ func main() {
2022-10-31:以下go语言代码输出什么?A:map[]:B:nil:C:Panic:D:编译错误. package main import "fmt" func main( ...