zoukankan      html  css  js  c++  java
  • P3805 【模板】manacher算法

    题目描述

    给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度.

    字符串长度为n

    输入输出格式

    输入格式:

    一行小写英文字符a,b,c...y,z组成的字符串S

    输出格式:

    一个整数表示答案

    输入输出样例

    输入样例#1: 
    aaa
    输出样例#1: 
    3

    说明

    字符串长度len <= 11000000

      记录p[i]表示i能向两边推(包括i)的最大距离,如果能求出p,则答案就是max(p)-1了(以i为中点的最长回文为2*p[i]-1,但这是加过字符后的答案,把加进去的字符干掉,最长回文就是p[i]-1)。假设当前能达到的最右边为R,对应的中点为pos,j是i的对称点。 


    1.当i<R时 

     

    由于L~R是回文,所以p[i]=p[j](i的最长回文和j的最长回文相同)。 
     

    这种情况是另一种:j的最长回文跳出L了。那么i的最长回文就不一定是j的最长回文了,但蓝色的肯定还是满足的。

    综上所述,p[i]=min(p[2*pos-i],R-i)。 


    2.当i>=R时 
    由于后面是未知的,于是只能暴力处理了。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    
    const int N=22000010;
    
    int L;
    char a[N>>1],s[N];
    int mid,maxr;
    int len[N];
    
    void init()
    {
        scanf("%s",a);
        int l=strlen(a);
        for(int i=0;i<l;++i)
            s[++L]='#',
            s[++L]=a[i];
        s[0]='@';
        s[++L]='#';
    }
    
    void manacher()
    {
        for(int i=1;i<=L;++i)
        {
            if(maxr>i)        //i在右端点左边 
                len[i]=min(len[mid*2-i],maxr-i);  //取与对称点回文长度和i->maxr的最小值 
            else    //i在maxr右边 
                len[i]=1;
            for(;s[i+len[i]]==s[i-len[i]];++len[i]);
            if(i+len[i]>maxr)
            {
                maxr=i+len[i];
                mid=i;
            }
        }
    }
    
    int main()
    {
        init();
        manacher();
        int ans=*max_element(len+1,len+L+1);
        printf("%d",ans-1);        //多算了一次i,要减去1 
        return 0;
    }
  • 相关阅读:
    如何配置android的adb环境变量
    react中 如何异步展示后台接口的提示消息
    java doc 相关
    linux 停止多个 进程...
    maven 打包 war 包含 WEB-INF/lib 目录
    对 ArrayList 进行分页.
    docker 磁盘清理 相关
    vue 在 html 中自定义 tag
    docker 限制 容器内存 使用
    mysql 基本语句
  • 原文地址:https://www.cnblogs.com/lovewhy/p/8439773.html
Copyright © 2011-2022 走看看