zoukankan      html  css  js  c++  java
  • P4555 [国家集训队]最长双回文串

    传送门

    搞回文串很容易想到manacher

    把每个回文串看成线段

    那就是求两个相邻线段的最长总长度

    设 l[ i ] 表示左端点为 i-1 时线段的最大长度,r[ i ] 表示右端点为 i+1 时线段的最大长度

    (这里 i 在manacher处理后的字符串a上,线段的最大长度是指原字符串上的长度)

    那么ans=max(ans, l[ i ] + r[ i ] ) (a[ i ] == ' # ')

    当 i 刚好为长线段的端点时的 l[ i ] 和 r[ i ] 在manacher 时可以处理好

    当 i 在长线段的内部时 l[ i ] 和 r[ i ] 可以递推出来

    l [ i ] =max(l[ i ],l[ i-2 ] -2) (i-2是因为 i 在a上,l[ i-2 ] - 2 是因为要保持回文,左右两边都要去掉)

    r [ i ] 也差不多处理

    具体看代码:

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const int N=1e7+7;
    char s[N],a[N];
    int f[N],l[N],r[N],ans,len;
    inline void read_s()
    {
        char ch=getchar();
        while(ch<'a'||ch>'z') ch=getchar();
        while(ch>='a'&&ch<='z') s[++len]=ch,ch=getchar();
    }
    int main()
    {
        read_s();
        len=len*2+1;
        for(int i=1;i<=len;i++)
            a[i]= i&1 ? '#' : s[i>>1];
        a[0]='$';
        int pos=0,mx=0;
        for(int i=1;i<=len;i++)
        {
            f[i]= i>=mx ? 1 : min(f[pos*2-i],mx-i);
            while(a[i+f[i]]==a[i-f[i]]) f[i]++;
            if(i+f[i]>mx) mx=i+f[i],pos=i;
            l[i-f[i]+1]=max(l[i-f[i]+1],f[i]-1);
            r[i+f[i]-1]=max(r[i+f[i]-1],f[i]-1);
        }
        for(int i=3;i<len;i+=2) l[i]=max(l[i],l[i-2]-2);//只要计算'#'的l,r数组
        for(int i=len-2;i>=3;i-=2) r[i]=max(r[i],r[i+2]-2);
        for(int i=3;i<len;i+=2) ans=max(ans,l[i]+r[i]);//主要i!=1&&i!=len,题目要求线段长度不能为0
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    2.ECMAScript 5.0
    1.Javascript简介
    9.定位
    HDU2032 杨辉三角
    HDU2058 The sum problem
    HDU2091 空心三角形
    HDU1166 敌兵布阵(树状数组模板题)
    HDU2049 不容易系列之(4)——考新郎
    Python网络爬虫与信息提取(三)(正则表达式的基础语法)
    HDU6576 Worker
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/9717299.html
Copyright © 2011-2022 走看看