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马拉车算法的更多相关文章

  1. Manacher(马拉车)算法(jekyll迁移)

    layout: post title: Manacher(马拉车)算法 date: 2019-09-07 author: xiepl1997 cover: 'assets/img/manacher.p ...

  2. manacher(马拉车算法)

    Manacher(马拉车算法) 序言 mannacher 是一种在 O(n)时间内求出最长回文串的算法 我们用暴力求解最长回文串长度的时间复杂度为O(n3) 很明显,这个时间复杂度我们接受不了,这时候 ...

  3. HDU - 3068 最长回文manacher马拉车算法

    # a # b # b # a # 当我们遇到回判断最长回文字符串问题的时候,若果用暴力的方法来做,就是在字符串中间添加 #,然后遍历每一个字符,找到最长的回文字符串.那么马拉车算法就是在这个基础上进 ...

  4. Manacher (马拉车) 算法:解决最长回文子串的利器

    最长回文子串 回文串就是原串和反转字符串相同的字符串.比如 aba,acca.前一个是奇数长度的回文串,后一个是偶数长度的回文串. 最长回文子串就是一个字符串的所有子串中,是回文串且长度最长的子串. ...

  5. 最长回文子串 —— Manacher (马拉车) 算法

    最长回文子串 回文串就是原串和反转字符串相同的字符串.比如 aba,acca.前一个是奇数长度的回文串,后一个是偶数长度的回文串. 最长回文子串就是一个字符串的所有子串中,是回文串且长度最长的子串. ...

  6. Manacher(马拉车)算法

    Manacher算法是一个求字符串的最长回文子串一种非常高效的方法,其时间复杂度为O(n).下面分析以下其实行原理及代码: 1.首先对字符串进行预处理 因为回文分为奇回文和偶回文,分类处理比较麻烦,所 ...

  7. [模板] Manacher(马拉车)算法

    用途 求回文子串 做法 先考虑回文子串以某字符为中心的情况,即长度为奇数 推着做,记rad[i]为以i位置为中心的最大半径(包含中点) 考虑怎么求rad[i].找之前的一个右端点最靠右的位置p,设它的 ...

  8. Manacher(马拉车)算法详解

    给定一个字符串,求出其最长回文子串 eg:  abcba 第一步: 在字符串首尾,及各字符间各插入一个字符(前提这个字符未出现在串里). 如  原来ma  /*  a    b a    b   c ...

  9. Manacher's Algorithm 马拉车算法

    这个马拉车算法Manacher‘s Algorithm是用来查找一个字符串的最长回文子串的线性方法,由一个叫Manacher的人在1975年发明的,这个方法的最大贡献是在于将时间复杂度提升到了线性,这 ...

随机推荐

  1. VS2010打包回顾

    1.  在vs2010 选择“新建项目”à“ 其他项目类型”à“ Visual Studio Installerà “安装项目”: 命名为:Setup1 . 这是在VS2010中将有三个文件夹, 1. ...

  2. LUR和缺页次数

    缺页:缺页中断就是要访问的页不在主存,需要操作系统将其调入主存后再进行访问. LRU(Least recently used)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问 ...

  3. VS2013程序打包报 ISEXP : error -****: An error occurred streaming

    原因缺少打包文件 解决方案: 找到打包文件 右击选择 downLoad selected item

  4. 我的spring cloud项目历程(2018.3~2018.9)

    前言 今天是9月17日,趁着山竹的临幸,得以在家里舒适的办公.项目从3月底开始,至今刚好半年.抽几十分钟,总结下半年的历程.对后面的项目,应该也有一点帮助吧. 学习前的七个问题 项目开始前,由于某些特 ...

  5. 进击的Python【第十二章】:mysql介绍与简单操作,sqlachemy介绍与简单应用

    进击的Python[第十二章]:mysql介绍与简单操作,sqlachemy介绍与简单应用 一.数据库介绍 什么是数据库? 数据库(Database)是按照数据结构来组织.存储和管理数据的仓库,每个数 ...

  6. 445 Add Two Numbers II 两数相加 II

    给定两个非空链表来代表两个非负整数.数字最高位位于链表开始位置.它们的每个节点只存储单个数字.将这两数相加会返回一个新的链表.你可以假设除了数字 0 之外,这两个数字都不会以零开头.进阶:如果输入链表 ...

  7. iOS开发 - CoreData框架 数据持久化

    Core Data Core Data是iOS5之后才出现的一个框架,它提供了对象-关系映射(ORM)的功能,即能够将OC对象转化成数据,保存在SQLite数据库文件中,也能够将保存在数据库中的数据还 ...

  8. 工作记录:JS正则表达式 angularjs ng-if ng-show ng-switch

    用了一下JS 正则表达式判断密码,很简单 学习了angularjs的ng-if ng-show ng-switch的区别并使用 https://www.cnblogs.com/54td/p/59743 ...

  9. 11.2Java-多态

    一.父类 public class Fu { public void show(){ System.out.println("父类"); } } 二.子类 public class ...

  10. Struts2------拦截器和标签库和注解开发

    一.解析Struts2源码中拦截器的执行 客户端请求Action,执行前端控制器,在前端控制器内部创建了Action的代理类,调用代理类的execute方法,在execute方法内部执行ActionI ...