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

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

题目传送门

题意简介

\(S\) 的最大子串长度,该子串由两个回文串拼接而成

思路

考虑 \(Manacher\) 算法,在求解以第 \(i\) 个位置为中点的最长回文半径的同时,分别求出以第 \(i\) 个位置为起止点的最长回文串长度,注意由于 \(r_i\) 是指最长回文半径,故存在某些位置由于并不是一个最长回文串的端点导致未被更新以之为起止点的最长回文串长度,需专门递推地更新一次

Code

#include<iostream>
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
const int N=1e5+5;
string tmp;
int n,r[N<<1],A[N<<1],B[N<<1],cnt=0,maxx;
char S[N<<1];
int main()
{
    IOS;
    cin>>tmp,tmp=" "+tmp;
    n=tmp.length()-1;
    S[0]='&';
    for(int i=1;i<=n;i++)
        S[(i<<1)-1]=tmp[i],S[i<<1]='&';
    int L=0,R=-1;
    for(int i=0;i<=(n<<1);i++)
    {
        if(i<=R) r[i]=min(r[L+R-i],R-i+1);
        while(i-r[i]>=0&&i+r[i]<=(n<<1)&&S[i-r[i]]==S[i+r[i]]) r[i]++;
        if(i+r[i]-1>R) L=i-r[i]+1,R=i+r[i]-1;
    }
    for(int i=0;i<=(n<<1);i++)
        A[i-r[i]+1]=max(A[i-r[i]+1],r[i]-1),B[i+r[i]-1]=max(B[i+r[i]-1],r[i]-1);
    for(int i=2;i<=(n<<1);i++)
        A[i]=max(A[i],A[i-2]-2);
    for(int i=(n<<1)-2;i>=0;i--)
        B[i]=max(B[i],B[i+2]-2);
    for(int i=2;i<(n<<1)-1;i+=2)
        maxx=max(maxx,A[i]+B[i]);
    cout<<maxx<<'\n';
    return 0;
}

完结撒花~

posted @ 2025-08-06 16:20  FallingGardenia  阅读(11)  评论(0)    收藏  举报