• P3805 【模板】manacher算法


    思路

    manache的板子
    manacher是一种能在O(n)的时间复杂度内求出最长回文子串的一种算法
    首先要在每个串之间加上'#',使得奇数长度和回文串和偶数长度的回文串可以被统一考虑
    之后要在首位加上'%',便于对出现位置进行讨论
    比如axa变为%#a#x#a#''
    算法过程和p[i](表示以i为中心的最长回文子串的半径)相关
    画图发现,i为中心的最长回文子串的长度是p[i]-1,开始位置是(i-p[i])/2
    然后manacher算法的核心就是这句

    p[i]=(mx>i)?min(p[2*id-i],mx-i):1
    

    mx是回文串右端点能延伸到的最远的位置,id是右端点能延伸到的最长回文串的中间位置,
    如果mx-i>p[2id-i],证明相对于id和i对称的回文串被id完全包括,由id的对称性可知p[i]=p[2id-i]
    如果mx-i<p[2*id-i],证明没有被完全包括,最长的回文最少是mx-i,然后由后面的while循环继续匹配
    如果mx<=i,则无法做出任何假设,只能让p[i]=1然后由后面的while暴力匹配

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int MAXN = 11000100;
    char s[MAXN];
    int n,p[MAXN*2];
    int manacher(char *s){
        char t[MAXN*2];
        int cnt=0,ans=0,id=0,mx=0;
        t[cnt++]='$';
        t[cnt++]='#';
        for(int i=1;i<=n;i++){
            t[cnt++]=s[i];
            t[cnt++]='#';
        }
        for(int i=0;i<=cnt;i++){
            p[i]=(mx>i)?min(p[2*id-i],mx-i):1;
            while(t[i-p[i]]==t[i+p[i]])
                p[i]++;
            if(i+p[i]>mx){
                mx=i+p[i];
                id=i;
            }
            if(p[i]-1>ans)
                ans=p[i]-1;
        }
        return ans;
    }
    int main(){
        scanf("%s",s+1);
        n=strlen(s+1);
        printf("%d
    ",manacher(s));
        return 0;
    }
    
  • 相关阅读:
    Hdu3022 Sum of Digits
    bzoj3864 Hero meet devil
    bzoj2448 挖油
    poj3783 Balls
    bzoj3802 Vocabulary
    Hdu5181 numbers
    Hdu5693 D Game
    图形填充之边标志算法
    图形填充之栅栏填充算法
    图形填充之种子填充算法
  • 原文地址:https://www.cnblogs.com/dreagonm/p/10510871.html
Copyright © 2020-2023  润新知