马拉车算法

马拉车算法

给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度。字符串长度len<=1e7

马拉车算法是用来求最长回文子串的。如果暴力的话是\(O(n^2)\)。能不能用到什么回文串的性质呢?

我们发现回文串内的任意一个串,都可以找到一个对于回文串对称中心对称的镜像串。用\(p[i]\)表示第i位的最大回文串长度/2。设\(R=max(j+p[j]), j<i\),也就是前面的回文串的最右边的位置,同时找到pos使得\(p[pos]=R\),也就是那个贡献最右回文串的中心位置。

如果情况是第一种,那么显然\(p[i]=p[j]\)。如果情况是第二种,那么说明,i的回文串长度至少为\(p[j]\),但是会延伸到R以外,因此暴力判断R以外的红色部分即可。

由于R不停往右挪,因此时间复杂度是\(O(n)\)。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int maxn=3e7+5;
char s[maxn], s2[maxn];
int n;

int p[maxn], pos, R, ans;
int Manachar(char *s){
    pos=R=ans=0; memset(p, 0, sizeof(p));
    for (int i=1; i<n; ++i){
        if (i<R) p[i]=min(p[pos*2-i], R-i); else p[i]=1;
        for (; i-p[i]>=0&&s[i+p[i]]==s[i-p[i]]; ++p[i]);
        if (p[i]+i>R) R=p[i]+i, pos=i;
    }
    for (int i=0; i<n; ++i) ans=max(ans, p[i]);
    return ans;
}

int main(){
    scanf("%s", s); n=strlen(s);
    for (int i=0; i<n; ++i) s2[i<<1]='O', s2[i<<1|1]=s[i];
    n<<=1; s2[n++]='O';
    printf("%d\n", Manachar(s2)-1);
    return 0;
}

原文地址:https://www.cnblogs.com/MyNameIsPc/p/9179331.html

时间: 2024-11-08 14:31:50

马拉车算法的相关文章

manacher马拉车算法

入门manacher最好文章:https://segmentfault.com/a/1190000003914228 我整理了模板代码:HDOJ3068马拉车模板 1 //讲解 https://segmentfault.com/a/1190000003914228 2 //manacher 算法模板 3 //求最长回文串 O(N) 4 #include <bits/stdc++.h> 5 using namespace std; 6 const int maxn=3e5+10; 7 char

字符串(马拉车算法,后缀数组,稀疏表):BZOJ 3676 [Apio2014]回文串

Description 考虑一个只包含小写拉丁字母的字符串s.我们定义s的一个子串t的“出 现值”为t在s中的出现次数乘以t的长度.请你求出s的所有回文子串中的最 大出现值. Input 输入只有一行,为一个只包含小写字母(a -z)的非空字符串s. Output 输出一个整数,为逝查回文子串的最大出现值. Sample Input [样例输入l] abacaba [样例输入2] www Sample Output [样例输出l] 7 [样例输出2] 4 HINT 一个串是回文的,当且仅当它从左

Manacher&#39;s Algorithm ----马拉车算法

本文是我对博友BIT祝威 和Grandyang ,以及寒小阳关于最长回文子串上关于马拉车算法理解的整理,若是对我的整理有所不懂得,建议去看BIT祝威的博客,很详细,以下纯属个人不成熟的理解. 首先,得先了解什么是回文串(我之前就不是很了解,汗).回文串就是正反读起来就是一样的,如"abba".关于采用时间复杂度为O(n^2),以每个字符为中心去向两端遍历寻找最大回文串的方法,可以见我之前些的博客,戳这里! 当我们遇到字符串为"aaaaaaaaa",之前的算法就会发生

2015 UESTC 搜索专题M题 Palindromic String 马拉车算法

Palindromic String Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/contest/show/61 Description 秋实大哥喜欢探索新鲜事物,最近他发明了一种新型回文串,叫K重回文串!今天他想用它来考考小朋友们. 秋实大哥给出了与K重回文串有关的信息 任何字符串都属于0重回文串,包括空字符串.    一个长度为N的字符串S,S是K(k≥1)重回文串,当且仅当S是回文串,且其长

什么是马拉车算法(Manacher&#39;s Algorithm)?

提出问题 最长回文子串问题:给定一个字符串,求它的最长回文子串长度. 如果一个字符串正着读和反着读是一样的,那它就是回文串.如a.aa.aba.abba等. 暴力解法 简单粗暴:找到字符串的所有子串,遍历每一个子串以验证它们是否为回文串.一个子串由子串的起点和终点确定,对于一个长度为n的字符串,共有n^2个子串.这些子串的平均长度大约是n/2,因此这个解法的时间复杂度是 \(O(n^3)\).明显不可取. 方法改进 回文子串是连续的,而且是对称的.长度为奇数回文串以最中间字符的位置为对称轴左右对

天梯杯 L2-008. 最长对称子串(马拉车算法应用)

最长对称子串 对给定的字符串,本题要求你输出最长对称子串的长度.例如,给定Is PAT&TAP symmetric?,最长对称子串为s PAT&TAP s,于是你应该输出11. 输入格式: 输入在一行中给出长度不超过1000的非空字符串. 输出格式: 在一行中输出最长对称子串的长度. 马拉车算法: 一)第一步是改造字符串S,变为T,其改造的方法如下: 在字符串S的字符之间和S的首尾都插入一个"#",如:S="abba"变为T="#a#b#b

Manacher 马拉车算法

首先感谢 https://www.cnblogs.com/grandyang/p/4475985.html这篇文章,给了我很大帮助,解释的很详细. 最近在学习lyd的算法竞赛书,学到求最长回文串的时候就看到了O(n)复杂度的Manacher算法,书上给的是hash+二分做法,复杂度为O(nlgn),所以我就去学习了一下Manacher算法. 上面大佬的文章比较详细了,我在这里再说一下我当时比较迷惑地方,以及我注意的一些细节 我这个人就是和细节过不去,一点细节上解释不明白我就感觉自己还是不会 如何

Manacher&#39;s Algorithm(马拉车算法)

Manacher Algorithm算法,俗称马拉车算法,其时间复杂为O(n).该算法是利用回文串的特性来避免重复计算的,至于如何利用,且由后面慢慢道来. 在时间复杂度为O(n^2)的算法中,我们在遍历的过程要考虑到回文串长度的奇偶性,比如说“abba”的长度为偶数,“abcba”的长度为奇数,这样在寻找最长回文子串的过程要分别考奇偶的情况,是否可以统一处理了? 一)第一步是改造字符串S,变为T,其改造的方法如下: 在字符串S的字符之间和S的首尾都插入一个“#”,如:S=“abba”变为T="#

吉哥系列故事——完美队形II(马拉车算法)

吉哥又想出了一个新的完美队形游戏! 假设有n个人按顺序站在他的面前,他们的身高分别是h[1], h[2] ... h[n],吉哥希望从中挑出一些人,让这些人形成一个新的队形,新的队形若满足以下三点要求,则就是新的完美队形: 1.挑出的人保持原队形的相对顺序不变,且必须都是在原队形中连续的: 2.左右对称,假设有m个人形成新的队形,则第1个人和第m个人身高相同,第2个人和第m-1个人身高相同,依此类推,当然如果m是奇数,中间那个人可以任意: 3.从左到中间那个人,身高需保证不下降,如果用H表示新队