manacher马拉车算法
Manacher算法讲解
总有人喜欢搞事情,出字符串的题,直接卡掉了我的40分
I.适用范围
manacher算法解决的是字符串最长回文子串长度的问题。
关键词:最长 回文 子串
II.算法
1.纯暴力怎么写?
枚举每个字串(n^2)
判断是否回文(n)
综上,时间为n^3。
能解决n < 300的数据
2.优化的暴力
枚举点(n)
从点开始向两边逐个扩展,统计回文串的长度(上界n,但随机情况下很小)
综上,时间为n^2。
在随机数据下,实际表现能达到大概(n^2 / logn)的速度。
能解决5000左右的数据。
我们定义回文串的半径为回文串的回文中心到回文串的一端中间有多少个字符(不包含中心,包含端点)
比如回文串floatiyyitaolf的半径就是7,而vanav的半径是2。
对于长度是奇数和偶数的串要分类讨论。
给个示意的代码:
for(int i = ;i <= n;i++) {
回文串的半径 k = ;
while(s[i-k] == s[i+k]) k++;
ans = max(k*+,ans);
}
3.更优秀的算法——manacher
manacher可以看作是对上面那个n^2算法的进一步优化。
在枚举点统计回文串的过程中,我们其实是计算出了一些有用的信息,这些信息可以被后面的点使用,而无需重复计算(跟kmp有点像?)。
具体来说,我们从左向右枚举点,每次记录一下以这个点为中心的最长回文子串的半径(以i为中心的最长半径记为p[i])。
我们要试着利用回文的性质,因为子串是回文的,所以对于任意一个点x,有s[x - k] = s[x + k] (k<= p[x])。这条性质可以省去重复比较字符的过程。
manacher的算法流程:
记录现在最大的(p[i] + i)为maxright,maxright对应的i为pos。
枚举下一个位置i时,i与maxright和pos有下面三种情况:

蓝星星代表i点,褐色星星代表i点关于pos的对称点j。
情况1:
p[j]较小,被p[pos]完全包含,那么由于pos的两边是对称的,那么蓝色区间一定是回文的,我们只要在蓝色区间的基础上再找更大的回文区间就可以了。
情况2:
p[j]较大,但我们只能保证红色区间是回文的,所以情况二中的蓝色区间是回文的,求更大的蓝色回文区间仍需要逐个扩展。
情况3:
此时i已经超出了maxright,不在红色范围,内此时只能逐个扩展。
每次扩展完毕要更新pos和maxright。
manacher还处理了一个问题:字串长度是奇数偶数要分类讨论。
具体方法是在每个字符的前后都保证有一个不在题目给的串里出现的字符,强行转化成奇数个字符。
AAADJ —> #A#A#A#D#J#
Code
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std; const int MAXN = + ; int n,ans;
int maxright,pos;
int p[MAXN<<];
char t[MAXN<<],s[MAXN<<]; inline int _max(int x,int y) {
return x > y ? x : y;
} inline int _min(int x,int y) {
return x < y ? x : y;
} int main() {
scanf("%s",t+);
n = strlen(t+);
s[] = '@';
for(register int i = ;i <= n;i++) {
s[i+i-] = '#';
s[i+i] = t[i];
}
n = n+n+; s[n] = '#';
for(register int i = ;i <= n;i++) {
if(i < maxright) p[i] = _min(p[pos+pos-i],maxright-i);
while(s[i-p[i]] == s[i+p[i]]) p[i]++;
ans = _max(ans,p[i]);
if(i+p[i] > maxright) maxright = i+p[i], pos = i;//要及时更新maxright
}
printf("%d\n",ans-);
return ;
}
manacher马拉车算法的更多相关文章
- Manacher(马拉车)算法(jekyll迁移)
layout: post title: Manacher(马拉车)算法 date: 2019-09-07 author: xiepl1997 cover: 'assets/img/manacher.p ...
- manacher(马拉车算法)
Manacher(马拉车算法) 序言 mannacher 是一种在 O(n)时间内求出最长回文串的算法 我们用暴力求解最长回文串长度的时间复杂度为O(n3) 很明显,这个时间复杂度我们接受不了,这时候 ...
- HDU - 3068 最长回文manacher马拉车算法
# a # b # b # a # 当我们遇到回判断最长回文字符串问题的时候,若果用暴力的方法来做,就是在字符串中间添加 #,然后遍历每一个字符,找到最长的回文字符串.那么马拉车算法就是在这个基础上进 ...
- Manacher (马拉车) 算法:解决最长回文子串的利器
最长回文子串 回文串就是原串和反转字符串相同的字符串.比如 aba,acca.前一个是奇数长度的回文串,后一个是偶数长度的回文串. 最长回文子串就是一个字符串的所有子串中,是回文串且长度最长的子串. ...
- 最长回文子串 —— Manacher (马拉车) 算法
最长回文子串 回文串就是原串和反转字符串相同的字符串.比如 aba,acca.前一个是奇数长度的回文串,后一个是偶数长度的回文串. 最长回文子串就是一个字符串的所有子串中,是回文串且长度最长的子串. ...
- Manacher(马拉车)算法
Manacher算法是一个求字符串的最长回文子串一种非常高效的方法,其时间复杂度为O(n).下面分析以下其实行原理及代码: 1.首先对字符串进行预处理 因为回文分为奇回文和偶回文,分类处理比较麻烦,所 ...
- [模板] Manacher(马拉车)算法
用途 求回文子串 做法 先考虑回文子串以某字符为中心的情况,即长度为奇数 推着做,记rad[i]为以i位置为中心的最大半径(包含中点) 考虑怎么求rad[i].找之前的一个右端点最靠右的位置p,设它的 ...
- Manacher(马拉车)算法详解
给定一个字符串,求出其最长回文子串 eg: abcba 第一步: 在字符串首尾,及各字符间各插入一个字符(前提这个字符未出现在串里). 如 原来ma /* a b a b c ...
- Manacher's Algorithm 马拉车算法
这个马拉车算法Manacher‘s Algorithm是用来查找一个字符串的最长回文子串的线性方法,由一个叫Manacher的人在1975年发明的,这个方法的最大贡献是在于将时间复杂度提升到了线性,这 ...
随机推荐
- 关于XAMPP Apache无法启动问题解决方案
安装好XAMPP后,启动Apache服务启动失败,然后从xampp安装目录下执行apache_start.bat文件,如下图 显示443端口被占用. 解决方法: 启动cmd,输入netstat -a ...
- Spring IOC 一——容器装配Bean的简单使用
下文:SpringIOC 二-- 容器 和 Bean的深入理解 写在前面 这篇文章去年写的,缘起于去年某段时间被领导临时"抓壮丁"般的叫过去做java开发,然后在网上找了一个 Sp ...
- HDU1175:连连看(搜索)
传送门 题意 给定一个n*m的矩阵,询问q次,两个方块是否能被消掉,弯折次数不超过两次 分析 这题写了有一个下午,思路很简单,但是有很多trick,(唉),我还是太弱 trick 初始判断:1.两点不 ...
- 利用爬虫将Yuan先生的博客文章爬取下来
由于一次巧遇,我阅读了Yuan先生的一篇博客文章,感觉从Yuan先生得博客学到很多东西,很喜欢他得文章.于是我就关注了他,并且想阅读更多出自他手笔得博客文章,无奈,可能Yuan先生不想公开自己得博客吧 ...
- c语言中的rand()函数用法
rand() rand()函数作用:用来产生随机数,但是,rand()的内部实现是用线性同余法实现的,是伪随机数,由于周期较长,因此在一定范围内可以看成是随机的. rand()函数返回:返回一个范围在 ...
- [Usaco2005 Jan]Sumsets 求和
Description Farmer John commanded his cows to search for different sets of numbers that sum to a giv ...
- Poj 2947 widget factory (高斯消元解同模方程)
题目连接: http://poj.org/problem?id=2947 题目大意: 有n种类型的零件,m个工人,每个零件的加工时间是[3,9],每个工人在一个特定的时间段内可以生产k个零件(可以相同 ...
- html 测试
斯蒂芬斯蒂芬 20:23你过来吧,我们好好谈一谈 好好学习 21:22这是一个无法避免的错误 作为一个新手,我在学习HTML文件的格式,我觉得博客园的编辑器很棒, 查看这些源代码让我学习到了许多知识. ...
- List与类之间的运用,即与javabean的应用
package com.wh.Object; public class Goods { private String name; private double price; private int n ...
- tomcat 修改端口
修改tomcat端口号: a) 去tomcat安装目录(或者解压目录)下的“conf”文件夹中找到文件“server.xml”(本例:“D:\Program Files\Apache Software ...