作用:

在线性时间内找到一个字符串的最大回文子串

原理:

奇偶变换:为处理字符串方便,现将给定的任意字符串进行处理,使所有可能的奇数/偶数长度的回文子串都转换成了奇数长度。

具体就是在每个字符的两边都插入一个特殊的符号。比如hhjj变成 #h#h#j#j#, aba变成 #a#b#a#;

为防止数组越界,可以在字符串的开始加入另一个特殊字符,比如“?#a#b#a#?” 。

定义一个辅助数组int p[],p[i]表示以s_new[i]为中心的最长回文的半径,例如:

可以看出,p[i]-1正好是原字符串中最长回文串的长度。
Manacher 算法之所以快,就快在对 p 数组的求法上有个捷径。

if(i < mx)//mx为以id为中心的最远扩展回文串的右边界,i为扫描到的点
{
p[i] = min(p[2 * id - i], mx - i);
}

  注解在代码里,例题链接:http://acm.hdu.edu.cn/showproblem.php?pid=3068

#include<stdio.h>
#include<string.h>
#include<algorithm>
#define mem(a, b) memset(a, b, sizeof(a))
using namespace std; char str[110010];
char new_s[110010 * 2]; //mannacher数组因为奇偶变换加了符号进去,数组要开原字符串2倍大小
int p[110010 * 2]; void get_news(int len)//构造新字符串
{
new_s[0] = '^';
new_s[1] = '#';
int j = 1;
for(int i = 0; i < len; i ++)
{
new_s[++ j] = str[i];
new_s[++ j] = '#';
}
j ++;
new_s[j] = '\0';
} int mannacher(int len)
{
mem(p, 0);
int mx = 0;
int id = 0;
int maxlen = -1;//答案,最长字符串长度初始化
for(int i = 1; i < len; i ++)
{
if(i < mx)//mx为以id为中心的最远扩展回文串的右边界,i为扫描到的点
{
p[i] = min(p[2 * id - i], mx - i);//需搞清楚上面那张图含义, mx和2*id-i的含义
}
else //i >= mx 不能利用对称性来直接求解p[i]了, 所以先p[i] = 1,然后暴力更新
p[i] = 1;
while(new_s[i - p[i]] == new_s[i + p[i]])//不需边界判断,因为左有'^',右有'\0'
p[i] ++;
if(mx < i + p[i])//每走一步i,都要和mx比较,我们希望mx尽可能的远,这样才能更有机会执行if (i < mx)这句代码,从而提高效率
{
id = i;
mx = i + p[i];
}
maxlen = max(maxlen, p[i] - 1);
}
return maxlen;
} int main()
{
while(scanf("%s", str)!=EOF)
{
int len = strlen(str);
get_news(len);
len = strlen(new_s);
int ans = mannacher(len);
printf("%d\n", ans);
}
return 0;
}

  

马拉车算法,mannacher查找最长回文子串的更多相关文章

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

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

  2. Manacher算法讲解——字符串最长回文子串

    引 入 引入 引入 Manachar算法主要是处理字符串中关于回文串的问题的,这没什么好说的. M a n a c h e r 算 法 Manacher算法 Manacher算法 朴素 求一个字符串中 ...

  3. Manacher's Algorithm 马拉车算法(求最长回文串)

    作用:求一个字符串中的最长子串,同时还可以求所有子串的长度. 题目链接: https://vjudge.net/contest/254692#problem/B 最长回文串长度的代码: int Man ...

  4. manacher算法_求最长回文子串长度

    很好的总结,转自: http://blog.csdn.net/dyx404514/article/details/42061017 总结为:两大情况,三小情况. 两大情况:I. i <= p 1 ...

  5. manacher算法学习(求最长回文子串长度)

    Manacher总结 我的代码 学习:yyb luogu题目模板 xzy的模板 #include<iostream> #include<cstdlib> #include< ...

  6. [hdu 3068] Manacher算法O(n)最长回文子串

    一个不错的讲解:https://github.com/julycoding/The-Art-Of-Programming-By-July/blob/master/ebook/zh/01.05.md # ...

  7. Manacher算法——求最长回文子串

    首先,得先了解什么是回文串.回文串就是正反读起来就是一样的,如“abcdcba”.我们要是直接采用暴力方法来查找最长回文子串,时间复杂度为O(n^3),好一点的方法是枚举每一个字符,比较较它左右距离相 ...

  8. 面试经典算法:马拉松算法,最长回文子串Golang实现

    求一个字符串中最长的回文子串. package main import "fmt" /* 马拉松算法,求最长回文子串,时间复杂度:线性 */ func main() { // 回文 ...

  9. 使用manacher算法解决最长回文子串问题

    要解决的问题 求一个字符串最长回文子串是什么.且时间复杂度 O(N) 具体描述可参考: LeetCode_5_最长回文子串 LintCode_200_最长回文子串 暴力解法 以每个字符为中心向左右两边 ...

随机推荐

  1. js通过高德地图获取当前位置的经度纬度

    效果图如下: 已经获取到了经度纬度了 代码如下: <!doctype html> <html> <head> <meta charset="utf- ...

  2. RDay2-Problem 2 B

    题目描述 小明家有n个信箱,前前后后来送信和取信的总次数为q,称为q次访问,其中这q次访问分成三种类型. 1:邮递员送来了一封信,放在了x号信箱. 2:小明取走了x号信箱的所有信(x信箱可能已经没有信 ...

  3. 使用kettle来根据时间戳或者批次号来批量导入数据,达到增量的效果。

    1.Kettle是一款国外开源的ETL工具,纯java编写,可以在Window.Linux.Unix上运行,数据抽取高效稳定.下载图形化界面的zip包格式的,直接解压缩使用即可.安装部署模式这里不说了 ...

  4. mysql字段有中英文,数字按照升序/降序 排序

    ORDER BY    CONVERT(name,SIGNED) ASC,    CONVERT(name USING gbk) DESC

  5. 03.DataStructure

    01.list ''' list 특징 - 1차원 배열 구조 형식) 변수 = [값1, 값2] - 다양한 자료형 저장 가능 - index 사용=순서 존재 형식) 변수[n] - 값 수정( ...

  6. Linux中jdk安装及配置

    第一步:准备好jdk安装包:             

  7. (转)InFluxDB数据库使用手册

    InfluxDB是一个开源的时序数据库,使用GO语言开发,特别适合用于处理和分析资源监控数据这种时序相关数据.而InfluxDB自带的各种特殊函数如求标准差,随机取样数据,统计数据变化比等,使数据统计 ...

  8. dagger2 依赖注入

    前言: 当 mvp + dagger2 + rxjava 三者遇上,架构更加清晰,代码更加灵活,巧妙结合. 依赖注入:是为了解耦,达到高内聚低耦合的目的,保证代码的健壮性.灵活性和可维护性. publ ...

  9. linux进阶指令

    1.df  查看磁盘空间  2.free   查看内存使用 -m 表示以mb位单位查看 total    总大小 used   使用过的空间 free 空闲的空间 shared 共享内存 buffer ...

  10. NOIP-扫雷游戏

    题目描述 扫雷游戏是一款十分经典的单机小游戏.在n行m列的雷区中有一些格子含有地雷(称之为地雷格),其他格子不含地雷(称之为非地雷格).玩家翻开一个非地雷格时,该格将会出现一个数字——提示周围格子中有 ...