• 最长双回文串


    题目大意:

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

    题解:
    若X,Y都是回文串且相邻,则共用一个’#‘。

    可以对于每个‘#’找出其左边界和右边界。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 100050
    char s0[N],s[2*N];
    int l0,len;
    int p[2*N],l[2*N],r[2*N];
    void manacher()
    {
        int mid=0,mx=0;
        for(int i=1;i<=len;i++)
        {
            if(i<=mx)p[i]=min(p[2*mid-i],mx-i+1);
            else p[i]=1;
            while(s[i+p[i]]==s[i-p[i]])p[i]++;
            l[i+p[i]-1]=max(p[i]-1,l[i+p[i]-1]);
            r[i-p[i]+1]=max(p[i]-1,r[i-p[i]+1]);
            if(i+p[i]-1>mx)
            {
                mid=i;
                mx=i+p[i]-1;
            }
        }
    }
    int main()
    {
        scanf("%s",s0+1);
        l0 = strlen(s0+1);
        s[0]='!';
        for(int i=1;i<=l0;i++)
        {
            s[++len]='#';
            s[++len]=s0[i];
        }
        s[++len]='#';
        s[++len]='@';
        manacher();
        for(int i=3;i<=len;i+=2)
            r[i]=max(r[i],r[i-2]-2);
        for(int i=len;i>=1;i-=2)
            l[i]=max(l[i],l[i+2]+2);
        int ans = 0;
        for(int i=1;i<=len;i+=2)
            ans=max(ans,r[i]+l[i]);
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    再回首Java第九天
    再回首Java第八天
    再回首Java一周记
    再回首Java第六天
    再回首Java第五天
    再回首Java第四天
    再回首Java第三天
    再回首Java第二天
    再回首Java第一天
    关于i++和++i理解
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10014582.html
Copyright © 2020-2023  润新知