有些时候,后缀自动机并不能解决某些问题,或者解决很麻烦。这时就有各种神奇的字符串算法了。

manacher算法用来O(|S|)地求出字符串S的最长的回文子串的长度。这是怎么做到的呢?

并不对劲的暴力选手在刚见到求字符串S的最长的回文串的长度这个问题时,第一反应就是枚举每一个位置为回文串的对称轴,再暴力地判断。由于回文串的对称轴可能在缝隙处,对于奇偶还要特判。这时最好每隔一个字符插入一个奇怪的字符。对暴力做一些优化,就是用二分+哈希来判断。不过这也只能o(|S| log2|S|)地做出来。能不能利用回文串的某些性质呢?

设r[i]表示以i为对称轴,是S[i+1]与S[i-1],S[i+2]与S[i-2],…,S[i+x]与S[i-x],相等的最大的x。定义s(i,r[i])表示以i为对称轴的且右端点为i+r[i]的回文串。

那么i-r[i]到i+r[i]这一段就是对称的。

记已算出的最大的i+r[i]为maxr (也就是已算出的回文串的右端点中最靠右的),maxr的i为maxi。

若要算出r[a],则:

若a>=maxr,直接按定义暴力地求出r[a]。

若a<maxr,则先找出a关于maxi的对称点b。则r[a]>=min(r[b],maxr-a)。

当r[b]<maxr-a时,a+r[b]<maxr,所以s(b,r[b])肯定被s(maxi,maxr)包含。由于a与b关于maxi对称,所以以a为对称轴的回文串中,肯定有一个等于ls(b,r[b])。又因为r[b]是b的最长回文子串的右端点,所以S[b-r[b]-1]!=S[b+r[b]+1],根据对称性又能推出S[a-r[b]-1]!=S[a+r[b]+1]。所以此时r[a]=r[b]。

当r[b]>=maxr-a时,b-r[b]<maxi-r[maxi],也就是说,s(b,r[b])中有一部分在s(maxi,maxr)外,不符合对称性。这一部分是不能算的。所以此时r[a]>=min(r[b],maxr-a)

这样先令r[a]=min(r[b],maxr-i),剩下的按定义暴力求就行了。

字符串S的最长的回文串的长度就是最大的r[i]了。这是因为如果算上奇怪的字符,那么r[i]对应的回文串长度是r[i]*2+1。修改后的字符串每隔一个字符就有一个奇怪的字符。这些奇怪的字符都相同,所以r[i]对应回文串的第一个字符和最后一个字符都是奇怪的字符(形如#a#b#a#或#a#a#)。那么不是奇怪的字符一共有(r[i]*2+1-1)/2=r[i]个。

至于时间复杂度,并不对劲的人并不想不证明。因为每次有意义的比较都是maxr之后的部分,比较过的部分又会更新maxr。总的来看就是maxr将整个字符串扫了一遍,时间复杂度是O(|S|),而且很好写。

不太清楚它能出成什么题?

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define maxn 11000010
using namespace std;
char s1[maxn],s2[maxn*];
int n,mr,mid,r[maxn*],ans;
int check(int x,int y)
{
while(s2[x-y]==s2[x+y])y++;
return y-;
}
int main()
{
scanf("%s",s1+);
n=strlen(s1+);
s2[]='B',s2[n*+]='C';
for(int i=;i<=n*+;i++)
{
if(i&)s2[i]='A';
else s2[i]=s1[i/];
}n=n*+;
mr=mid=;
for(int i=;i<=n;i++)
{
if(i>=mr)
r[i]=check(i,);
else
r[i]=check(i,min(r[mid*-i],mr-i));
if(r[ans]<r[i])
ans=i;
if(i+r[i]>mr){mid=i;mr=i+r[i];}
}
printf("%d",r[ans]);
return ;
}
//Shing has healthy hands.

并不对劲的manacher

并不对劲的manacher算法的更多相关文章

  1. HDU3068 回文串 Manacher算法

    好久没有刷题了,虽然参加过ACM,但是始终没有融会贯通,没有学个彻底.我干啥都是半吊子,一瓶子不满半瓶子晃荡. 就连简单的Manacher算法我也没有刷过,常常为岁月蹉跎而感到后悔. 问题描述 给定一 ...

  2. manacher算法专题

    一.模板 算法解析:http://www.felix021.com/blog/read.php?2040 *主要用来解决一个字符串中最长回文串的长度,在O(n)时间内,线性复杂度下,求出以每个字符串为 ...

  3. lintcode最长回文子串(Manacher算法)

    题目来自lintcode, 链接:http://www.lintcode.com/zh-cn/problem/longest-palindromic-substring/ 最长回文子串 给出一个字符串 ...

  4. 1089 最长回文子串 V2(Manacher算法)

    1089 最长回文子串 V2(Manacher算法) 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 回文串是指aba.abba.cccbccc.aaaa ...

  5. 51nod1089(最长回文子串之manacher算法)

    题目链接: https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1089 题意:中文题诶~ 思路: 我前面做的那道回文子串的题 ...

  6. LeetCode 5 Longest Palindromic Substring manacher算法,最长回文子序列,string.substr(start,len) 难度:2

    https://leetcode.com/problems/longest-palindromic-substring/ manacher算法相关:http://blog.csdn.net/ywhor ...

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

    主要学习自:http://articles.leetcode.com/2011/11/longest-palindromic-substring-part-ii.html 问题描述:回文字符串就是左右 ...

  8. 【转】最长回文子串的O(n)的Manacher算法

    Manacher算法 首先:大家都知道什么叫回文串吧,这个算法要解决的就是一个字符串中最长的回文子串有多长.这个算法可以在O(n)的时间复杂度内既线性时间复杂度的情况下,求出以每个字符为中心的最长回文 ...

  9. Manacher算法

    Manacher算法是求回文串最高效的算法,能在线性时间内求出以每一个字符为中心的最长回文串.   首先,我们都能想出$O(N^2)$求出每一个字符为中心的最长回文串的算法.那么我们考虑这样一种情况. ...

随机推荐

  1. hexo干货系列:(八)hexo文章自动隐藏侧边栏

    前言 使用Jacman主题的时候发现打开具体文章后,侧边栏还是会展示,我想要的效果是自动隐藏侧边栏,并且展示目录.但是当我修改了主题配置文件里面close_aside属性为true的时候,发现侧边栏隐 ...

  2. 『NYIST』第八届河南省ACM竞赛训练赛[正式赛一]-CodeForces 236A,虽然很水,但有一个很简单的函数用起来方便

    A. Boy or Girl time limit per test 1 second memory limit per test 256 megabytes input standard input ...

  3. CodeForce 448C 木片填涂问题

    题目大意:有多片木片需要填涂,可以每次横着涂一行,也可以一次涂一列,当然你涂一行时遇到中间长度不够高的木片,填涂到此中断 这题目运用dfs能更容易的解出,虽然还是十分不容易理解 #include &l ...

  4. [luoguP1186] 玛丽卡(spfa)

    传送门 因为要随机删除一条边,而枚举所有边肯定会超时,经过发现,先求出一遍最短路,而要删除的边肯定在最短路径上,删除其他的边对最短路没有影响. 所以可以先求出最短路,再枚举删除最短路上的每一条边再求最 ...

  5. numpy模块

    NumPy简介: NumPy 是高性能科学计算和数据分析的基础包:它是pandas等其他工具的基础. NumPy的主要功能: 1. ndarray,一个多维数组结构,高效且节省空间 (最主要的功能) ...

  6. Maven的scope依赖作用域说明

    Maven的scope依赖作用域说明 1.test范围指的是测试范围有效,在编译和打包时都不会使用这个依赖 2.compile范围指的是编译范围有效,在编译和打包时都会将依赖存储进去 3.provid ...

  7. BZOJ2501: [usaco2010 Oct]Soda Machine

    n<=50000个区间,求哪个点被覆盖区间数量最多,输出这个数量. 差分模板..然而数组忘开两倍.. #include<stdio.h> #include<string.h&g ...

  8. Codeforces 954 D Fight Against Traffic

    Discription Little town Nsk consists of n junctions connected by m bidirectional roads. Each road co ...

  9. 寒武纪camp Day6

    补题进度:10/10 A(树形dp) 略 B(dp) 题意: 给出一个n个关键节点的机械手臂,最开始是竖直的,即关键点在二维平面上的坐标分别是(0,0) (0,100) (0,200) (0,300) ...

  10. 寒武纪camp Day2

    补题进度:8/10 A(计数+BIT) 题意: 给一个长度为n的数组a[],任意选0<=i<=j<n,将a[i]~a[j]从小到大排序,形成新的数组.问有多少个不同的新数组. N,a ...