Manacher 算法学习笔记
算法用处:
解决最长回文子串的问题(朴素型)。
算法复杂度
我们不妨先看看其他暴力解法的复杂度:
- \(O(n^3)\)
枚举子串的左右边界,然后再暴力判断是否回文,对答案取 \(max\) 。 - \(O(n^2)\)
枚举回文子串的对称轴,向两边扩展,对答案取 \(max\) 。 - \(O(n)\)
\(\texttt{Manacher}\) 算法。
显然我们的 \(\texttt{Manacher}\) 是十分优秀的。。。
实现原理
\(\text{step 1}\)
首先我们需解决一个问题:
回文串的长度有有奇也有偶,这会对我们的算法带来不利,如何解决?
我们可以对原串进行一些改造:
我们在原串的每两个字符之间都插入同一个字符(保证与原来串中的字符不重复)。
举个例子:
对于一个串:\(S = \texttt{"abbabaab"}\)
我们进行上述操作:\(S^\prime = \texttt{"/a/b/b/a/b/a/a/b/"}\)
我们把它变成这样,于是我们发现:
对于长度为奇数的回文串,它的回文中心是原串的字符;
对于长度为偶数的回文串,它的回文中心是加入的字符;
那么我们 \(S\) 中的任意一个回文子串都会在 \(S^\prime\) 中唯一对应一个字符。
于是我们可以开始在 \(S^\prime\) 上进行操作。
\(\text{step 2}\)
我们对于 \(S^\prime\) 中的每一个字符 \(S^\prime[i]\) 维护一个 \(f[i]\)
表示以 \(S^\prime[i]\) 为回文中心可以扩展的最远位置和 \(i\) 的下标之差(也就是这两点之间的距离)
我们只要求出了每一个位置的 \(f[i]\),那么该位置作为对称中心时的回文串的长度就是 \(f[i]\):
- 对于 \(S^\prime[i] \in S\),(比如
/q/w/q/),显而易见。。。 - 对于 \(S^\prime[i] \notin S\),(比如
/y/y/),这也是显而易见的。。。
于是我们考虑求出这个 \(f[i]\),答案就是 \(\max\limits_{1\leq i \leq N}\{f[i]\}\)
\(\text{step 3}\)
我们需要发现一个很重要的性质:
- 如果对于一个回文子串,其内部还有一个回文子串,
- 那么也必定会有一个与之全等的字串与它关于这个较大回文子串的对称中心对称
这个性质应该是显然的。。。
在整个算法进行过程中,我们记录一个 \(MaxRight\) 和一个 \(Mid\)
其中 \(MaxRight\) 表示我们扩展过的最远的位置,\(Mid\) 表示它对应的回文中心。
那么对于我们当前的 \(i\) :
- 若 \(i<MaxRight\) ,那么我们可以把 \(f[i]\) 初始化为 \(\min\{f[j], MaxRight-i\}\)
其中的 \(j\) 表示我们刚刚提到过的,该位置对称的那个点,
即以 \(i\) 为对称中心的回文子串与以 \(j\) 为对称中心的回文子串关于 \(Mid\) 对称。 - 若 \(i>MaxRight\) ,那么就不管。。。
然后,我们暴力的去扩展 \(f[i]\),并最终用固定下来的 \(i\) 和 \(f[i]\) 来更新 \(MaxRight\) 和 \(Mid\)。
这样就可以在 \(O(n)\) 时间内求出所有的 \(f[i]\) 了。(复杂度证明?我好像不会。。。)
模板题
Luogu
板子题不解释
/*--------------------------------
--Author: The Ace Bee-------------
--Blog: www.cnblogs.com/zsbzsb----
--This code is made by The Ace Bee
--------------------------------*/
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <cmath>
#include <ctime>
#define rg register
#define clr(x, y) memset(x, y, sizeof x)
using namespace std;
template < typename T > inline void read(T& s) {
s = 0; int f = 0; char c = getchar();
while (!isdigit(c)) f |= (c == '-'), c = getchar();
while (isdigit(c)) s = s * 10 + (c ^ 48), c = getchar();
s = f ? -s : s;
}
const int _(11000010);
int n, f[_ << 1];
char s[_ << 1], tmp[_];
inline int manacher() {
int n = strlen(s + 1);
for (rg int i = 1; i <= n; ++i) tmp[i] = s[i];
for (rg int i = 1, j = 0; i <= n; ++i) s[++j] = '`', s[++j] = tmp[i];
s[0] = s[n * 2 + 1] = '`', n = n * 2 + 1;
int mx = 0, mid;//mx 即 MaxRight,mid 即 Mid
for (rg int i = 1; i <= n; ++i) {
f[i] = i < mx ? min(mx - i, f[mid * 2 - i]) : 0;
while (s[i - f[i] - 1] == s[i + f[i] + 1]) ++f[i];
if (i + f[i] > mx) mx = i + f[i], mid = i;
}
int res = 0;
for (rg int i = 1; i <= n; ++i) res = max(res, f[i]);
return res;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
#endif
scanf("%s", s + 1);
printf("%d\n", manacher());
return 0;
}
Manacher 算法学习笔记的更多相关文章
- Manacher算法学习笔记 | LeetCode#5
Manacher算法学习笔记 DECLARATION 引用来源:https://www.cnblogs.com/grandyang/p/4475985.html CONTENT 用途:寻找一个字符串的 ...
- Manacher算法学习笔记
前言 Manacher(也叫马拉车)是一种用于在线性时间内找出字符串中最长回文子串的算法 算法 一般的查找回文串的算法是枚举中心,然后往两侧拓展,看最多拓展出多远.最坏情况下$O(n^2)$ 然而Ma ...
- C / C++算法学习笔记(8)-SHELL排序
原始地址:C / C++算法学习笔记(8)-SHELL排序 基本思想 先取一个小于n的整数d1作为第一个增量(gap),把文件的全部记录分成d1个组.所有距离为dl的倍数的记录放在同一个组中.先在各组 ...
- Johnson算法学习笔记
\(Johnson\)算法学习笔记. 在最短路的学习中,我们曾学习了三种最短路的算法,\(Bellman-Ford\)算法及其队列优化\(SPFA\)算法,\(Dijkstra\)算法.这些算法可以快 ...
- 某科学的PID算法学习笔记
最近,在某社团的要求下,自学了PID算法.学完后,深切地感受到PID算法之强大.PID算法应用广泛,比如加热器.平衡车.无人机等等,是自动控制理论中比较容易理解但十分重要的算法. 下面是博主学习过程中 ...
- Johnson 全源最短路径算法学习笔记
Johnson 全源最短路径算法学习笔记 如果你希望得到带互动的极简文字体验,请点这里 我们来学习johnson Johnson 算法是一种在边加权有向图中找到所有顶点对之间最短路径的方法.它允许一些 ...
- Manacher算法学习 【马拉车】
好久没写算法学习博客了 比较懒,一直在刷水题 今天学一个用于回文串计算问题manacher算法[马拉车] 回文串 回文串:指的是以字符串中心为轴,两边字符关于该轴对称的字符串 ——例如abaaba 最 ...
- 算法学习笔记——sort 和 qsort 提供的快速排序
这里存放的是笔者在学习算法和数据结构时相关的学习笔记,记录了笔者通过网络和书籍资料中学习到的知识点和技巧,在供自己学习和反思的同时为有需要的人提供一定的思路和帮助. 从排序开始 基本的排序算法包括冒泡 ...
- manacher算法学习(求最长回文子串长度)
Manacher总结 我的代码 学习:yyb luogu题目模板 xzy的模板 #include<iostream> #include<cstdlib> #include< ...
随机推荐
- 攻防世界 robots题
来自攻防世界 robots [原理] robots.txt是搜索引擎中访问网站的时候要查看的第一个文件.当一个搜索蜘蛛访问一个站点时,它会首先检查该站点根目录下是否存在robots.txt,如果存在, ...
- YouTube为创作者提供了更多赚钱的途径
编辑 | 于斌 出品 | 于见(mpyujian) 大家提到YouTube可能还有些陌生,只是听说过,但因为一些原因并没有实际应用过,但其实YouTube就是设立在美国的一个视频分享网站,让使用者上载 ...
- Docker安装、命令详情、层级架构、docker服务启动失败解决方法
容器背景: 层级架构: 容器对比传统化虚拟机: 可以把docker理解成是一款自带软件(比如:nignx.tomcat.....)的镜像操作系统(首先是要下载镜像) 以下是Windows环境安装Do ...
- go语言快速入门教程
go快速入门指南 by 小强,2019-06-13 go语言是目前非常火热的语言,广泛应用于服务器端,云计算,kubernetes容器编排等领域.它是一种开源的编译型程序设计语言,支持并发.垃圾回收机 ...
- Vim:Vim入门级配置
转:https://vimjc.com/vimrc-config.html Vim配置文件.vimrc Vim编辑器相关的所有功能开关都可以通过.vimrc文件进行设置. .vimrc配置文件分系统配 ...
- L3-022 地铁一日游
floyd算法建立新图,dfs标记~ #include<bits/stdc++.h> using namespace std; ; const int inf=1e9; int d[max ...
- linux与python3安装redis
1.linux安装redis服务 apt-get install redis* 进入客户端管理 redis-cli 启动服务 service redis startservice redis rest ...
- Codeforces Round #619 (Div. 2) A. Three Strings
You are given three strings aa , bb and cc of the same length nn . The strings consist of lowercase ...
- 转入软工后第一节java课的作业
这个作业,鸽了好久.本来大家都在中秋前发了,我摸摸索索加上各种缓慢的学习,终于是将他做完了. 做完之后,java最基本的输入输出功能都基本学习到了.下面附上代码: import java.util.* ...
- 杭电 1114 Piggy-Bank 完全背包问题
Piggy-Bank Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total ...