1. 程式人生 > 其它 >P4287 [SHOI2011]雙倍迴文

P4287 [SHOI2011]雙倍迴文

技術標籤:P4287SHOI2011雙倍迴文

文章目錄

R e s u l t Result Result

...


H y p e r l i n k Hyperlink Hyperlink

https://www.luogu.com.cn/problem/P4287


D e s c r i p t i o n Description Description

若一個迴文串長度為4的倍數且從中間斷開後的兩個子串仍是迴文串稱這個串是雙倍迴文的。給定一個長度為 n n n的串,求其最長雙倍迴文子串
資料範圍: n ≤ 5 × 1 0 5 n\leq 5\times 10^5 n5×105


S o l u t i o n Solution Solution

跑馬拉車時順便判斷前面是否能拓展過來即可

時間複雜度: O ( n ) O(n) O(n)


C o d e Code Code

#include<cstdio>
#include
<cctype>
#include<cstring> #include<algorithm> #define LL long long #define N 5000010 using namespace std;char s[N],news[N]; int n,newn,p[N]; inline LL read() { char c;LL d=1,f=0; while(c=getchar(),!isdigit(c)) if(c=='-') d=-1;f=(f<<3)+(f<<1)+c-48; while(c=getchar(),isdigit
(c)) f=(f<<3)+(f<<1)+c-48; return d*f; } inline void Init() { news[0]='~';news[1]='|';newn=2; for(register int i=0;i<n;i++) news[newn++]=s[i],news[newn++]='|'; news[newn]=10;return; } inline int Manacher() { int mid=1,mx=1,ans=0; for(register int i=1;i<newn;i++) { if(i<mx) p[i]=min(mx-i,p[2*mid-i]);else p[i]=1; while(news[i-p[i]]==news[i+p[i]]) p[i]++; if(mx<i+p[i]) { if(i&1) for(register int j=max(mx,i+4);j<i+p[i];j++) if(!(j-i&3)&&p[i-(j-i)/2]>(j-i)/2) ans=max(ans,j-i); mid=i; mx=i+p[i]; } } return ans; } signed main() { n=read();scanf("%s",s);Init(); printf("%d\n",Manacher()); }