题解 P3805 【【模板】manacher算法】
题解 P3805 【【模板】manacher算法】
我们先看两个字符串:
ABCCBA
ABCDCBA
显然这两字符串是回文的
然而两个串的对称中心的特性不同,第一个串,它的对称中心在两个C中间,然而第二个串,它的对称中心就是D。这样我们如果要记录回文串的对称中心,就显得复杂了。
为了解决这个问题,把两种情况统一起来,我们就在字母之间插入隔板,这样两个问题就统一了,因为所有的对称中心都会有个字符与之对应。像这样
~A|B|C|C|B|A|
(注意到我们这里还插入了一个“~”,原因我们待会说明)
manacher为什么有如此优秀的复杂度呢?让我用比图片还要清楚的文字说明一下
对于一个回文串,有且仅有一个对称中心。且叫它回文对称中心。
在一个回文串内,任选一段区间 X ,一定存在关于”回文对称中心“对称的一个区间,且把这个区间叫做关于区间_X_的对称区间。
区间和对称区间一定全等。( 1)(十分显然)
由_(1)得 ,若一个区间的对称区间是回文串,这个区间必定是一个回文串。在大的回文串内,它们回文半径相等。 (2)_
然而我们通过确定关系预先得到的回文半径,它的数值,必定小于等于这个位置真实的回文串半径。(十分显然)
因此,为利用特性(2),我们若记录每个字符作为回文对称中心时的回文串的半径,就可以知道该字符,它,关于某另一个对称中心(称此对称中心对应的回文串叫做“大回文串“)对称的,在大的回文半径内,对应字符的部分回文半径了。
记录这些数据到p数组。同时记录一个mid,一个r,分别代表 已经确定的右侧最靠右的回文串的对称中心和右边界
然而,考虑一些情况,发现我们只能确认我们已知的回文串内的对称关系和回文半径等量关系,关于这个大回文串右侧的世界,我们一无所知。
那么,当我们扫描到一个新的字符时,怎么先确定它的部分回文半径呢?
若当前扫描到的位置为i,若mid<=i<=r,则我们可以找到它的一个对称点。这个点的位置是多少?是mid×2-i。我们现在对其推导一下。
设:这个新点位置为i,它关于mid对称的点为j,将整个字符串看做以下标0位置为原点的数轴,我们由中点公式可得:
( i + j ) / 2 = mid
方程两边同时乘以二, 得:
i + j = 2 * mid
移项, 得:
j=2*mid-i
证毕。
就是这样小学生都会的推导过程,几乎每篇题解都是 直接摆出结论 ,不给出证明和推导,要求学习者自己”找规律” , 我真是不敢苟同。希望大家以后发题解要严谨一点,至少自己没有真正理解就不要发题解,让人觉得manacher是难以学习的算法。至少当我在学习的时候,是一头雾水。
所以,拓展一个新点时,我们不必从这个点左右两边第一个位置开始向两边拓展,可以预先确定一部分回文串。就是因为这个,manacher的复杂度是线性的。
若扩展一个新的关于该字符的回文半径,可以先确定一部分P[i]。
且我们知道,我们能确定的范围,其右侧不得大于r,即:p[i]+i<=r 移项得:p[i] <= r-i
故此,要取一个min 这里给出代码:
P[i]=min(P[mid*2-i],r-i)
最终答案是
P(max)-1
讲到这里,应该十分清楚了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=11000002;
char data[maxn<<1];
int p[maxn<<1];
int cnt=1;
#define RP(t,a,b) for(int t=(a),edd=(b);t<=edd;t++)
inline void qr(){
char c=getchar();
data[0]='~';
data[1]='|';
while(c<'a'||c>'z')
c=getchar();
while(c>='a'&&c<='z'){
data[++cnt]=c;
data[++cnt]='|';
c=getchar();
}
return;
}
int maxans,rb,mid;
inline int cmpless(int x,int y){
if(x<y)
return x;
return y;
}
int main(){
//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout);
qr();
RP(t,1,cnt){
if(t<rb)
p[t]=cmpless(p[(mid<<1)-t],rb-t);
else
p[t]=1;
while(data[t-p[t]]==data[t+p[t]])
//暴力拓展左右两侧,当t-p[t]==0时,由于data[0]是'~',自动停止。
//故不会下标溢出。
p[t]++;
if(p[t]+t>rb)
//更新mid和rb,保持rb是最右的才能保证我们提前确定的部分回文半径尽量多。
rb=p[t]+t,mid=t;
if(p[t]>maxans)
maxans=p[t];
}
cout<<maxans-1<<endl;
return 0;
}
祝大家学习愉快
题解 P3805 【【模板】manacher算法】的更多相关文章
- 洛谷P3805 [模板]Manacher算法 [manacher]
题目传送门 题目描述 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 字符串长度为n 输入输出格式 输入格式: 一行小写英文字符a,b,c...y,z组成的字符 ...
- 模板 manacher算法
题目描述 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 字符串长度为n 输入输出格式 输入格式: 一行小写英文字符a,b,c...y,z组成的字符串S 输出格 ...
- 洛谷.3805.[模板]manacher算法
题目链接 之前做很早了没写这篇,补上. 记录当前ex[]最大的回文中心id和最远延伸范围mx! 关于串的构造: 应该是 @ #A#B#C#B#A# $ ,而不是 @ A#B#C#B#A $ 比如 @a ...
- 洛谷 P3805 【模板】manacher算法
洛谷 P3805 [模板]manacher算法 洛谷传送门 题目描述 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 字符串长度为n 输入格式 一行小写英文字符 ...
- [洛谷P3805]【模板】manacher算法
题目大意:给你一个字符串,求出它的最长回文字段 题解:$manacher$算法 卡点:$p$数组未开两倍空间 C++ Code: #include <cstdio> #include &l ...
- Manacher || Luogu P3805【模板】manacher算法
题面:[模板]manacher算法 代码: #include<cstdio> #include<cstring> #include<iostream> #defin ...
- 洛谷 P3805【模板】manacher算法
题目链接:https://www.luogu.com.cn/problem/P3805 Manacher算法$O(n)$: 求以每个字符为中心的最长回文串的半径:如果要求可以以字符间隙为回文中心,就要 ...
- 【洛谷 P3805】 【模板】manacher算法
题目链接 manacher算法:在线性时间内求一个字符串中所有/最长回文串的算法. 先来考虑一下暴力的算法,枚举每个中点,向两边扩展,时间复杂度\(O(n^2)\). 来分析下此算法的缺点. 1.因为 ...
- P3805 【模版】manacher算法(manacher)
P3805 [模版]manacher算法 题目描述 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 字符串长度为n 输入输出格式 输入格式: 一行小写英文字符a ...
随机推荐
- ELK之filebeat替代logstash收集日志
filebeat->redis->logstash->elasticsearch 官网下载地址:https://www.elastic.co/downloads/beats/file ...
- c# winform 最小化到托盘
STEP1.添加托盘图标控件NotifyIcon(直接从工具箱中拖动添加即可) STEP2.添加(重写)窗口尺寸变动函数Form1_Resize private void Main_SizeChang ...
- 鼠标悬浮弹出标题制作JQuery
今天给客户制作的网站里面加个效果,当鼠标在列表图片之外时,标题不显示,当鼠标悬浮在图片之上时,标题从底部弹出. 效果图如下: 鼠标悬浮前: 鼠标悬浮后: html代码如下: <ul class= ...
- django中日志使用学习记录
在setting中加入以下代码 LOGGING = { 'version': 1, 'disable_existing_loggers': True, 'formatters': { 'verbose ...
- 【音乐App】—— Vue-music 项目学习笔记:歌曲列表组件开发
前言:以下内容均为学习慕课网高级实战课程的实践爬坑笔记. 项目github地址:https://github.com/66Web/ljq_vue_music,欢迎Star. 当前歌曲播放列表 添加歌曲 ...
- 一波三折ST-Link
前言 原创文章,转载引用务必注明链接,水平有限,如有疏漏,欢迎指正. 本文使用Markdown写成,为获得更好的阅读体验和正常的链接.图片显示,请访问我的博客原文: http://www.cnblog ...
- java 格式化json字符串
须要下载:gson-2.2.4.jar
- props default 数组(Array)/对象(Object)的默认值应当由一个工厂函数返回
1.场景: Object: <!-- 步骤 --> <template> <div> <div class="m-cell"> &l ...
- eclipse高速查找一个变量、方法或者类被引用的地方
近期不停debug,拿到一个变量之后总是要先概览一下才好下手,之前一直用Ctrl+F来做,太麻烦. 今天查了下eclipse使用,发现有快捷键,用法: 先双击要查看的变量.方法或者类,使之被选中,然后 ...
- cocos2d-x-lua基础系列教程五(lua单例)
lua-单例 function newAccount(initlizedBanlance) local self = {balance = initlizedBanlance} local show ...