引入

引入

Manachar算法主要是处理字符串中关于回文串的问题的,这没什么好说的。

M

a

n

a

c

h

e

r

Manacher算法

Manacher算法

朴素

求一个字符串中以每个点为中心的最长回文子串,这是

m

a

n

a

c

h

e

r

manacher

manacher 直接解决的问题。

以每个点为中心的回文子串是连续的,它并不像字符串的

b

o

r

d

e

r

border

border ,因此可以二分,于是在不知道

m

a

n

a

c

h

e

r

manacher

manacher 的情况下其实可以用字符串哈希+二分,只不过是

O

(

n

l

o

g

n

)

O(nlogn)

O(nlogn) 的。

但是

m

a

n

a

c

h

e

r

manacher

manacher 可以

O

(

n

)

O(n)

O(n) 算出,因此在有些专门卡

l

o

g

log

log 的题目中

m

a

n

a

c

h

e

r

manacher

manacher 有不可比拟的优越性。

我们不妨设以

i

i

i 为中心的最长回文子串长度为

F

[

i

]

2

+

1

F[i]*2+1

F[i]∗2+1 ,

m

a

n

a

c

h

e

r

manacher

manacher 实际上是利用了一个回文字符串内的

F

[

]

F[]

F[] 的性质。

一个回文字符串,因为它是对称的,因此在仅考虑此字符串的情况下,它的

F

F

F 数组也是对称的,这便是

m

a

n

a

c

h

e

r

manacher

manacher 算法的核心了吧。

因此,我们考虑从左到右依次计算

F

[

i

]

F[i]

F[i] ,当遍历到一个点

i

i

i 时,首先

F

[

i

1

]

F[i-1]

F[i−1] 肯定已经算出来了。

如果

F

[

i

1

]

=

=

0

F[i-1]==0

F[i−1]==0 就直接暴力扩展 i ,否则,如果

F

[

i

2

]

<

F

[

i

1

]

1

F[i-2] < F[i-1]-1

F[i−2]<F[i−1]−1,说明什么呢?

F

[

i

]

=

F

[

i

2

]

F[i]=F[i-2]

F[i]=F[i−2],一定是这样的.

  1. F

    [

    i

    ]

    F[i]

    F[i] 肯定不能小于

    F

    [

    i

    2

    ]

    F[i-2]

    F[i−2] ,因为这个回文子串以

    i

    1

    i-1

    i−1 为对称中心,两边对称的两点,既然其中

    i

    2

    i-2

    i−2 可以扩大到

    F

    [

    i

    2

    ]

    F[i-2]

    F[i−2],且在

    i

    1

    i-1

    i−1 为中心的大回文串内 ,由于对称性,因此

    [

    i

    F

    [

    i

    2

    ]

    ,

    i

    +

    F

    [

    i

    2

    ]

    ]

    [i-F[i-2],i+F[i-2]]

    [i−F[i−2],i+F[i−2]] 范围内也一定是个回文串。

  2. F

    [

    i

    ]

    F[i]

    F[i] 也不能大于

    F

    [

    i

    2

    ]

    F[i-2]

    F[i−2] ,因为以每个点为中心的回文子串是连续的,

    F

    [

    i

    ]

    >

    F

    [

    i

    2

    ]

    F[i]>F[i-2]

    F[i]>F[i−2] 意味着

    F

    [

    i

    ]

    F[i]

    F[i] 可以为

    F

    [

    i

    2

    ]

    +

    1

    F[i-2]+1

    F[i−2]+1,而由于

    F

    [

    i

    2

    ]

    <

    F

    [

    i

    1

    ]

    1

    F[i-2] < F[i-1]-1

    F[i−2]<F[i−1]−1 ,对于

    i

    2

    i-2

    i−2 来说,

    F

    [

    i

    2

    ]

    +

    1

    F[i-2]+1

    F[i−2]+1 仍然在大回文串范围内,因此

    F

    [

    i

    2

    ]

    F[i-2]

    F[i−2] 肯定就不止这个数了。

然后呢,是不是可以继续利用这个大红串呢?我们还可以考虑

F

[

i

3

]

F[i-3]

F[i−3] 是否小于

F

[

i

1

]

2

F[i-1]-2

F[i−1]−2 来决定

F

[

i

+

1

]

F[i+1]

F[i+1] ,考虑

F

[

i

4

]

F[i-4]

F[i−4] 是否小于

F

[

i

1

]

3

F[i-1]-3

F[i−1]−3 来决定

F

[

i

+

2

]

F[i+2]

F[i+2] ……直到超出红框或者:有一个

F

[

i

2

x

]

F

[

i

1

]

1

x

F[i-2-x] ≥ F[i-1]-1-x

F[i−2−x]≥F[i−1]−1−x,这时候,

F

[

i

+

x

]

F[i+x]

F[i+x] 至少能扩大到红框边界吧,因为它的对称点都能扩大到红框边界。然后,再把

F

[

i

+

x

]

F[i+x]

F[i+x] 暴力往外扩。

我们会发现,整个过程中,每次往外扩一定能使前面所有的

i

+

F

[

i

]

i+F[i]

i+F[i] 的最大值变大,因此,它是线性的。

转化

很明显,对于一个回文字符串而言,并不一定中心是一个字符,也有可能是两个相同的字符的中界,即回文串长度为偶数,因此,一般把原串中每两个字符中间添一个没出现过的字符,于是所有的

F

[

i

]

2

+

1

F[i]*2+1

F[i]∗2+1(包括边界的)都会变成

(

F

[

i

]

2

+

1

)

2

+

1

(F[i]*2+1)*2+1

(F[i]∗2+1)∗2+1 ,这样就可以解决长度为偶数的情况。

模板

void Manacher(char *s,int *F,int n) {// 已是转化后的 S
F[1] = 0;
for(int i = 2;i <= n;i ++) {
int j = i;
while(j < i-1+F[i-1] && j+F[i-1-(j-i+1)] < i-1+F[i-1]) F[j] = F[i-1-(j-i+1)],j ++;
F[j] = max(0,i-1+F[i-1] - j);
while(j+F[j] < n && j-F[j] > 1 && s[j+F[j]+1] == s[j-F[j]-1]) F[j] ++;
i = j;
}
return ;
}

Manacher算法讲解——字符串最长回文子串的更多相关文章

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

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

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

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

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

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

  4. hihoCoder #1032 : 最长回文子串 [ Manacher算法--O(n)回文子串算法 ]

    传送门 #1032 : 最长回文子串 时间限制:1000ms 单点时限:1000ms 内存限制:64MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相 ...

  5. Manacher算法:求解最长回文字符串,时间复杂度为O(N)

    原文转载自:http://blog.csdn.net/yzl_rex/article/details/7908259 回文串定义:"回文串"是一个正读和反读都一样的字符串,比如&q ...

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

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

  7. 马拉车算法,mannacher查找最长回文子串

    作用: 在线性时间内找到一个字符串的最大回文子串 原理: 奇偶变换:为处理字符串方便,现将给定的任意字符串进行处理,使所有可能的奇数/偶数长度的回文子串都转换成了奇数长度. 具体就是在每个字符的两边都 ...

  8. Manacher模板( 线性求最长回文子串 )

    模板 #include<stdio.h> #include<string.h> #include<algorithm> #include<map> us ...

  9. Manacher算法--O(n)回文子串算法

    转自:http://blog.csdn.net/ggggiqnypgjg/article/details/6645824 O(n)回文子串算法 注:转载的这篇文章,我发现下面那个源代码有点bug... ...

随机推荐

  1. 6. Docker-compose配置Dockerfile使用

    Docker-compose实际是管理基于一个镜像启动的容器的. 使用docker-compose.yml文件以及Dockerfile文件在生成自定义镜像的同时启动当前镜像,并且由docker-com ...

  2. 【C++ 字符串题目】 输入三个人名,按字母顺序排序输出

    题目来源:https://acm.ujn.edu.cn Problem A: [C++ 字符串] 输入三个人名,按字母顺序排序输出 Time Limit: 1 Sec  Memory Limit: 1 ...

  3. Mybatis架构原理(二)-二级缓存源码剖析

    Mybatis架构原理(二)-二级缓存源码剖析 二级缓存构建在一级缓存之上,在收到查询请求时,Mybatis首先会查询二级缓存,若二级缓存没有命中,再去查询一级缓存,一级缓存没有,在查询数据库; 二级 ...

  4. SAP Grid control( ALV Grid 列表 自定义 按钮)

    ALV 列表和按钮 效果 源代码 PROGRAM bcalvc_tb_menu_with_def_but. *&&&&&&&&& ...

  5. 如何获取GC(垃圾回收器)的STW(暂停)时间?

    前言 在现代的容器化和微服务应用中,因为分布式的环境和错综复杂的调用关系,APM(Application Performance Monitoring 应用性能监控)显得尤为重要,它通过采集应用程序各 ...

  6. windows下telnet的用法

    前言 这里利用Windows7下如何使用Telnet命令给大家总结如下: 第一步:在控制面板里,点击"程序"选项 第二步:在程序选项下,点击"打开或关闭Windows功能 ...

  7. Tapdata “设擂招贤”携手 LeetCode 举办全球极客技术竞赛

      2021年11月28日 Tapdata 专场全球极客技术竞赛将在 LeetCode 平台开赛,面向程序员"设擂招贤",打擂成功的前50名挑战者将优先获得 Tapdata 高端技 ...

  8. java面向对象编程---方法

    二.方法 1.方法的重载 1.1 方法的签名 方法的唯一标识就是方法的签名:方法的名字和参数列表: 一个类中不能出现两个方法的签名完全一样的方法 1.2 方法的重载 方法名相同但参数列表不同称之为方法 ...

  9. umask计算创建文件、目录的默认权限

    很多人以为 创建文件默认权限就是 666-umask=创建文件的默认权限 创建目录的默认权限就是 777-umask=创建目录的默认权限   这种计算其实是不严谨的 为什么我们创建的文件的权限是 64 ...

  10. Solution -「ABC 217」题解

    D - Cutting Woods 记录每一个切割点,每次求前驱后驱就好了,注意简单判断一下开闭区间. 考场上采用的 FHQ_Treap 无脑莽. #include <cstdio> #i ...