• [模板] Manacher(马拉车)算法


    用途

    求回文子串

    做法

    先考虑回文子串以某字符为中心的情况,即长度为奇数

    推着做,记rad[i]为以i位置为中心的最大半径(包含中点)

    考虑怎么求rad[i]。找之前的一个右端点最靠右的位置p,设它的中心是j

    如果有i<p,那么找到i关于j的对称点2*j-i,那么一定$rad[i]>=min{rad[2*j-i],[p-i+1]}$

    如果i>=p,那前面做的东西对我求i没什么帮助,rad[i]>=1

    然后再暴力往后判断rad[i]能不能再大一点

    因为这个右端点最靠右的位置一定是递增的,所以能感受出这是一个O(n)的算法

    为了解决串长为偶数的问题,我们在每两个字符间(以及开头结尾?)都插个相同的特殊符号;为了避免可能的溢出,在最开始再插个别的符号

    例题

     1 #include<bits/stdc++.h>
     2 #define CLR(a,x) memset(a,x,sizeof(a))
     3 using namespace std;
     4 typedef long long ll;
     5 typedef pair<int,int> pa;
     6 const int maxn=2.2e7+10;
     7 
     8 inline ll rd(){
     9     ll x=0;char c=getchar();int neg=1;
    10     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
    11     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    12     return x*neg;
    13 }
    14 
    15 char s[maxn];
    16 int r[maxn];
    17 
    18 int main(){
    19     //freopen("","r",stdin);
    20     int i,j,k;
    21     scanf("%s",s+1);s[0]='!';
    22     int len=strlen(s+1);
    23     for(i=len;i>=0;i--){
    24         s[i<<1]=s[i],s[i<<1|1]='#';
    25     }len=len*2+1;
    26     int mp=0,mi=0,ans=0;
    27     for(i=1;i<=len;i++){
    28         r[i]=i<=mp?min(mp-i+1,r[mi*2-i]):1;
    29         while(s[i+r[i]]==s[i-r[i]]) r[i]++;
    30         if(i+r[i]-1>mp) mp=i+r[i]-1,mi=i;
    31         ans=max(ans,r[i]);
    32     }printf("%d
    ",ans-1);
    33     return 0;
    34 }
  • 相关阅读:
    Drupal Coder 模块远程命令执行分析(SA-CONTRIB-2016-039)
    Python 实现 ZoomEye API SDK
    程序员互动联盟第一届编码大赛第二题解题分享
    python中各进制之间的转换
    记一次ctf比赛解密题的解决(可逆加密基本破解之暴力破解)
    使用JsonConfig控制JSON lib序列化
    openMRS项目
    Harmonic Number(调和级数+欧拉常数)
    Pairs Forming LCM(素因子分解)
    Uva 11395 Sigma Function (因子和)
  • 原文地址:https://www.cnblogs.com/Ressed/p/9957413.html
Copyright © 2020-2023  润新知