• 洛谷 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

  • 相关阅读:
    scss-数据类型
    scss-@import
    scss-&父选择器标识符
    scss-嵌套属性
    Python之NumPy(axis=0 与axis=1)区分
    Java map 详解
    java之JDBC多条语句执行
    p-value值的认识
    numpy.random之常用函数
    Python random模块sample、randint、shuffle、choice随机函数
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9881263.html
Copyright © 2020-2023  润新知