zoukankan      html  css  js  c++  java
  • [Manacher]【学习笔记】

    终于填坑啦......马拉车


    课件上说的好短,但是明白了,讲解稍微修改一下抄上行了,比扩展KMP好写多了

    求以每个字符为中心的最长回文串的半径。
    如果要求可以以字符间隙为回文中心,就要在每两个字符之间及两端加入一个’#’,然后再解决。
    令r[i]为以i为中心的最长回文半径。从左往右依次求r数组。
    当前要求r[i],曾经的j+r[j]-1最大是p,对应的下标为a。如果r[2*a-i]+i-1<p,r[i]=r[2*a-i];否则r[i]≥p-i+1,暴力向后扩展。

    2*a-i就是i关于a的对称位置,上面那句很显然啊<p的时候就被包括在a为中心的回文串里呀

    实现上,直接r[i]=i<p?min(p-i+1,r[2*a-i]):1,然后往两边扩展就行了

    模板题:HDU3068

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int N=2e6+5;
    int n;
    char s[N],a[N];
    int r[N];
    void Manacher(char s[],int n){
        int p=0,a,ans=0;
        for(int i=1;i<=n;i++){
            r[i]=i<p?min(p-i+1,r[2*a-i]):1;
            while(s[i-r[i]]==s[i+r[i]]) r[i]++;
            if(i+r[i]-1>p) p=i+r[i]-1,a=i;
            ans=max(ans,r[i]);
        }
        printf("%d
    ",ans-1);
        //for(int i=1;i<=n;i++) printf("%d ",r[i]);puts("
    ");
    }
    void iniStr(char s[]){
        for(int i=1;i<=n;i++)
            a[(i<<1)-1]='#',a[i<<1]=s[i];
        a[(n<<1)+1]='#';
        a[0]='@';a[(n<<1)+2]='$';
    }
    int main(){
        freopen("in","r",stdin);
        while(scanf("%s",s+1)!=EOF){
            n=strlen(s+1);
            iniStr(s);
            Manacher(a,n<<1|1);
        }
    }
  • 相关阅读:
    语句
    1101 事务存储引擎触发器函数
    1029 作业
    1029 数据库表以及行的基本操作
    1023 笔记
    1022 作业
    1022 笔记
    1021 笔记
    查看pip已经安装过的包
    查看Python支持的.whl文件版本
  • 原文地址:https://www.cnblogs.com/candy99/p/6395305.html
Copyright © 2011-2022 走看看