zoukankan      html  css  js  c++  java
  • 洛谷 P4555 [国家集训队]最长双回文串 解题报告

    P4555 [国家集训队]最长双回文串

    题目描述

    顺序和逆序读起来完全一样的串叫做回文串。比如acbca是回文串,而abc不是(abc的顺序为abc,逆序为cba,不相同)。

    输入长度为(n)的串(S),求(S)的最长双回文子串(T),即可将(T)分为两部分(X)(Y),((|X|,|Y|≥1))且(X)(Y)都是回文串。

    输入输出格式

    输入格式:

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

    输出格式:

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

    说明

    对于(100\%)的数据,(2≤|S|≤10^5)


    按套路先把每个位置为中心的回文串长度用(manacher)求出来。

    然后比较暴力的想法是直接线段树做一下,虽然也可以通过不过不优雅。

    预处理出每个点为开头或结尾的最长回文串长度,然后枚举断点就可以了。

    如何预处理?发现可以先通过中心的最长回文串预处理一部分,然后扫描一遍,更新非最长的长度。

    具体的说,比如(pre_i)代表(i)开头的最长回文串,那么显然是有(pre_i=max(pre_{i-2}-2,pre_i))的(这里已经插入了'#')

    这个技巧用的比较多了,要注意使用。


    Code:

    #include <cstdio>
    #include <cstring>
    const int N=2e5+10;
    int a[N],t[N],L[N],R[N],n,ans,r;
    char s[N],c[N];
    int min(int x,int y){return x<y?x:y;}
    int max(int x,int y){return x>y?x:y;}
    int main()
    {
        memset(t,0x3f,sizeof(t));
        scanf("%s",c+1);
        n=strlen(c+1);
        s[0]=s[1]='$';
        for(int i=1;i<=n;i++) s[i*2]=c[i],s[i*2+1]='$';
        n=(n<<1)+1;
        for(int rig=0,mid,i=1;i<=n;i++)
        {
            a[i]=i>rig?1:min(rig-i,a[(mid<<1)-i]);
            while(s[i-a[i]]==s[i+a[i]]) ++a[i];
            --a[i];
            if(a[i]+i>rig) rig=a[i]+i,mid=i;
            L[i-a[i]]=max(L[i-a[i]],a[i]);
            R[i+a[i]]=max(R[i+a[i]],a[i]);
        }
        for(int i=3;i<=n;i+=2) L[i]=max(L[i],L[i-2]-2);
        for(int i=n;i>0;i-=2) R[i]=max(R[i],R[i+2]-2);
        for(int i=1;i<=n;i+=2) ans=max(ans,L[i]+R[i]);
        printf("%d
    ",ans);
        return 0;
    }
    

    2018.10.31

  • 相关阅读:
    spring-boot 中application.properties的各种配置
    spring-boot 集合mybatis 的分页查询
    spring boot热部署pom.xml配置
    ssm框架整合
    mybatis逆向工程
    整合hibernate的lucene大数据模糊查询
    QBC查询、离线条件查询(DetachedCriteric)和分页查询模版
    虚拟机vmnet0、vmnet1和vmnet8的区别
    centOS7-配置网络地址
    在windows中使用Navicat连接Linux虚拟机中的mysql数据库
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9881263.html
Copyright © 2011-2022 走看看