马拉车,O(n)求回文串

对整个马拉车算法步骤做个总结:

  • 第一步:将每个原字母用两个特殊字符包围如:
aaa --> #a#a#a#
abab -->#a#b#a#b
同时可以由这个翻倍的字符串得到一个性质:
如果在此串中,以特殊字符,如'#'为回文中心,那么在原串中回文长度就是偶数,如果是以正常字符为回文中心,那么在原串中的回文长度就是奇数

这样可以使得所有的奇数长度的回文串变成偶数长度

  • 第二步:设置P数组P[N*3];代表S[i]的回文半径(包括自身),并设置id为迄今为止回文半径最大的字符位置,max为id+P[id],该回文串的右边界位置

  • 第三步:求p数组,这里存在一个结论:

    如果mx > i,那么P[i] >= min(P[2 * id - i], mx - i)。

    2id-i,将其转化到x坐标上看,正好是i关于id的对称点,可以这么理解:由于mx>i,可知i-->mx是在已知范围以内的,因为以i为回文中心的回文串是与以其关于对称点j=2id-i存在长度至少为mx-i相同回文半径的。

    如图:(x和y至少是同样长的,因为以j为中心的是回文串,同id同i,根据回文串性质可得)

  • 第四步:对于p数组的认识,p数组是在原字符串翻倍后的基础上进行运算的,很显然,若p[i]=6,那么原串的回文长度(不是回文半径)是5 :设原半径为ans,回文长度为len,那么len=ans2-1;而此时半径为x=ans2,转化可得len=x-1;

这里贴上两份模板

模板1:

void init()
{
len1=strlen(s);
str[0]='(';
str[1]='#';
for(int i=0;i<len1;i++)
{
str[i*2+2]=s[i];
str[i*2+3]='#';
}
len2=len1*2+2;
str[len2]=')';
}
void Manacher()
{
memset(p,0,sizeof(p));
int id=0,mx=0;
for(int i=1;i<len2;i++)
{
if(mx>i) p[i]=min(mx-i,p[2*id-i]);
else p[i]=1;
for(;str[i+p[i]]==str[i-p[i]];p[i]++);
if(p[i]+i>mx)
{
mx=p[i]+i;
id=i;
}
}
}

模板2:

int Init(int n)
{
cpy[0]='(';cpy[1]='#';
for(int i=0,j=2;i<n;j+=2,i++)
{
cpy[j]=a[i];
cpy[j+1]='#';
}
n=n*2+3;
cpy[n-1]=')';
return n;
}
void Manacher(char *s,int n,int *p)
{
for(int i=1,j=0,k;i<n;i+=k)
{
while(s[i-j-1]==s[i+j+1]) j++;
p[i]=j;
for(k=1;k<=p[i]&&p[i-k]!=p[i]-k;k++)
{
p[i+k]=min(p[i-k],p[i]-k);
}
j=max(j-k,0);
}
}

马拉车,O(n)求回文串的更多相关文章

  1. Palindrome - URAL - 1297(求回文串)

    题目大意:RT   分析:后缀数组求回文串,不得不说确实比较麻烦,尤其是再用线段数进行查询,需要注意的细节地方比较多,比赛实用性不高......不过练练手还是可以的.   线段数+后缀数组代码如下: ...

  2. 2021.12.10 P5041 [HAOI2009]求回文串(树状数组求逆序对)

    2021.12.10 P5041 [HAOI2009]求回文串(树状数组求逆序对) https://www.luogu.com.cn/problem/P5041 题意: 给一个字符串 \(S\) ,每 ...

  3. LOJ 2452 对称 Antisymmetry——用hash求回文串数

    概念 用hash求最长回文串/回文串数 首先,易知,回文串具有单调性. 如果字符串 $s[l...r]$ 为回文串串,那么 $s[x...y]$($l < x, y < r$ 且 $|l- ...

  4. manacher算法,求回文串

    用来求字符串最长回文串或者回文串的总数量 #include<map> #include<queue> #include<stack> #include<cma ...

  5. hdu 3294 manacher 求回文串

    感谢: http://blog.csdn.net/ggggiqnypgjg/article/details/6645824/ O(n)求给定字符串的以每个位置为中心的回文串长度. 中心思想:每次计算位 ...

  6. hihocoder 1032 manachar 求回文串O(n)

    #include <cstdio> #include <iostream> #include <algorithm> #include <queue> ...

  7. HDU 5371(2015多校7)-Hotaru&#39;s problem(Manacher算法求回文串)

    题目地址:HDU 5371 题意:给你一个具有n个元素的整数序列,问你是否存在这样一个子序列.该子序列分为三部分,第一部分与第三部分同样,第一部分与第二部分对称.假设存在求最长的符合这样的条件的序列. ...

  8. 拓展KMP求回文串

    题目:hdu3613: 题意:有26字母对应的价值,然后给出以个串,把它分成两段字串,如果字串是回文串,串的价值就是每个字符和,不是就为0.求最大价值. 博客 分析:拓展KMP的应用求回文字串. #i ...

  9. 3676: [Apio2014]回文串 求回文串长度与出现次数的最大值

    「BZOJ3676」[Apio2014] 回文串   Description 考虑一个只包含小写拉丁字母的字符串s.我们定义s的一个子串t的“出 现值”为t在s中的出现次数乘以t的长度.请你求出s的所 ...

随机推荐

  1. 【146】ArcObjects类库索引

    ArcObjects 类库(一) ----------------------------------------------------------------------------------- ...

  2. P4244 [SHOI2008]仙人掌图 II

    传送门 仙人掌直径,以前好像模拟赛的时候做到过一道基环树的直径,打了个很麻烦的然而还错了--今天才发现那就是这个的弱化版啊-- 如果是树的话用普通的dp即可,记\(f[u]\)表示\(u\)往下最长能 ...

  3. [Swift通天遁地]一、超级工具-(15)使用SCLAlertView制作强大的Alert警告窗口和Input编辑窗口

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  4. selenium对51job进行职位爬虫

    selenium 爬虫流程如下: 1.对某职位进行爬虫 ---如:自动化测试 2.用到IDE为 pycharm 3.爬虫职位导入到MongoDB数据库中 4.在线安装 pip install pymo ...

  5. 因Window服务器自动更新并重启导致WebSphere服务停止服务故障一例

    最近公司购买了两台Windows Server 2008 R2服务器用于提供提供Web服务,A机器安装了IHS+DM+WAS8.5集群,B机器安装了Oracle11gR2用于数据存储,两台机器均可连接 ...

  6. poj2367 Genealogical tree

    思路: 拓扑排序,这里是用染色的dfs实现的.在有环的情况下可以判断出来,没有环的情况下输出拓扑排序序列. 实现: #include <vector> #include <cstri ...

  7. reduce的特殊用法

    //计算数组中每个元素出现的次数var arr = ["apple","orange","apple","orange" ...

  8. 如何快速排查解决Android中的内存泄露问题

    概述 内存泄露是Android开发中比较常见的问题,一旦发生会导致大量内存空间得不到释放,可用内存急剧减少,导致运行卡顿,部分功能不可用甚至引发应用crash.对于复杂度比较高.多人协同开发的项目来讲 ...

  9. Python安装笔记

    1.教程

  10. VC++函数只被调用一次

    如何保证某个函数只被调用一次   一个函数caller会在其内部调用另外一个函数callee,现在的情况是,caller可能会在多个地方被多次调用,而你希望callee只在第一次被调用时被调用一次.一 ...