• BZOJ_2565_最长双回文串_manacher


    BZOJ_2565_最长双回文串_manacher

    Description

    顺序和逆序读起来完全一样的串叫做回文串。比如acbca是回文串,而abc不是(abc的顺序为“abc”,逆序为“cba”,不相同)。
    输入长度为n的串S,求S的最长双回文子串T,即可将T分为两部分XY,(|X|,|Y|≥1)且XY都是回文串。

    Input

    一行由小写英文字母组成的字符串S

    Output

    一行一个整数,表示最长双回文子串的长度。

    Sample Input

    baacaabbacabb

    Sample Output

    12


    由于每个插入的'$'都对应原串中相邻的两个字符。

    我们可以枚举所有的'$'然后找向左延伸的最长回文l[]和向右延伸的最长回文r[]。

    manacher的时候更新单个'$'的l[]和r[]。

    然后l[]从右往左,r[]从左往右推一遍。l[i]=max(l[i],l[i+2]-2)    r[i]=max(r[i],r[i-2]-2)

    最后求答案即可,注意答案串的左右回文串长度大于0。

    代码:

    #include <cstdio>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define N 200050
    char w[N];
    int a[N],n,p[N],r[N],l[N];
    int main() {
        scanf("%s",w+1);
        int i;
        n=strlen(w+1);
        for(i=1;i<=n;i++) a[i*2-1]='$',a[i*2]=w[i];
        n=n<<1|1; a[n]='$';
        int mx=0,lst,ans=0;
        for(i=1;i<=n;i++) {
            if(i<=mx) p[i]=min(p[2*lst-i],mx-i+1);
            else p[i]=1;
            while(i-p[i]>=1&&i+p[i]<=n&&a[i-p[i]]==a[i+p[i]]) p[i]++;
            if(mx<i+p[i]-1) mx=i+p[i]-1,lst=i;
            r[i-p[i]+1]=max(r[i-p[i]+1],p[i]-1);
            l[i+p[i]-1]=max(l[i+p[i]-1],p[i]-1);
        }
        for(i=1;i<=n;i+=2) r[i]=max(r[i],r[i-2]-2);
        for(i=n;i>=1;i-=2) l[i]=max(l[i],l[i+2]-2);
        for(i=1;i<=n;i+=2) if(l[i]&&r[i]) ans=max(ans,l[i]+r[i]);
        printf("%d
    ",ans);
    }
    
    
  • 相关阅读:
    Keepalived安装配置
    Playbook 角色(Roles) 和 Include 语句
    Ansible Playbook
    ansible的Ad-hoc命令
    Android线程简介
    宝岛探险,DFS&BFS
    再解炸弹人,dfs&bfs
    解救小哈——bfs广搜
    解救小哈——dfs深搜
    数的全排列
  • 原文地址:https://www.cnblogs.com/suika/p/9126387.html
Copyright © 2020-2023  润新知