ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

manacher 算法

2022-09-16 21:03:42  阅读:296  来源: 互联网

标签:int manacher noon 算法 对称中心 回文


回文串

回文串是正着读和反着读都一样的字符串。

例如: abcba,noon。

manacher 算法就是用来求解一个字符串中最大回文串的长度。

算法过程

1.预处理
由于回文串分为偶回文串和奇回文串,这导致一个回文串的对称中心可能是一个也可能是两个,不方便处理。

abcba 的对称中心是c
noon 的对称中心是oo

所以我们可以在初始字符串的每个字符之间插入特殊字符(只要该字符不出现在原字符串即可)

noon 插入\(\$\),变为\(\$n\$o\$o\$n\$\)
插入之后回文性质没有改变,并且所有的回文串都变成了奇回文串,方便我们进行后续操作。

2.manacher 算法主体

定义数组p[i]表示以第i个字符为对称中心的最长回文串的半径,那么p[i]-1就是以第i个字符为对称中心的回文串长度(因为要去除插入的字符$)
用mx表示目前找到的回文串最右端的位置,该回文串的中心用mid表示

看上面这张图,我们要求p[i],j为i关于mid的对称点,而且我们已知p[j],那么就有
p[i]=min(mx-i,p[j])
这是因为在mx左边的部分可以用p[j]确定p[i]的长度,因为他们是关于mid对称的也就是完全一样的。
但是右边的部分不能保证,要用暴力法判断。
时间复杂度O(n)
详细请看代码
例题P3805 【模板】manacher 算法

#include<bits/stdc++.h>
using namespace std;
const int N=1.1e7+10;
char a[2*N],s[2*N];
int p[2*N];
int n;
int cnt=0;
void change(){
    s[cnt++]='^';//这个东西防止越界
    s[cnt++]='$';
    for(int i=0;i<n;++i)s[cnt++]=a[i],s[cnt++]='$';
}
int manacher(){
    int mx=0,mid=0,ans=0;
    for(int i=0;i<cnt;++i){
        if(i<mx)p[i]=min(mx-i,p[mid*2-i]);
        else p[i]=1;
        while(s[i+p[i]]==s[i-p[i]])p[i]++;//暴力判断右边的部分
        if(mx<i+p[i])mx=i+p[i],mid=i;//更新右边界
        //ans=max(ans,p[i]-1);
        if(ans<p[i]-1)ans=p[i]-1;//更新答案
    }
    return ans;

}
int main(){
    scanf("%s",a);
    n=strlen(a);
    change();
    //printf("%s\n",s);
    printf("%d",manacher());
    return 0;
}

参考

标签:int,manacher,noon,算法,对称中心,回文
来源: https://www.cnblogs.com/hetailang/p/16697844.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有