1. 程式人生 > >BZOJ2565 最長雙回文串 manacher

BZOJ2565 最長雙回文串 manacher

getch bzoj2565 debug inline 正常 pragma zoj manacher gcc

終於找到水題了感動。。

manacher模板都會吧。不會請點擊左側友鏈,找到FYJ大佬的博客,可以看他博客,或通過教他泡妹子等正常方式讓他給你講manacher。

首先,我們在進行manager的過程中,可以求出每個位置為中心的最長回文子串長度

那麽,我們可以枚舉斷點,把以該點結尾的前面最長回文子串長度與從該點開頭的最長回文子串長度加起來,取max,就能找到我們想要的答案了。

每找到一個中心及它的半徑,都掃一遍它的覆蓋區間,進行統計?

於是我們就找到了一個n²的優秀做法了[/手動滑稽]

技術分享圖片

繼續思考,以某個點為起點的最長長度,必定是從它的前面節點轉移來的(我們在馬拉車找回文串時將長度存在了這個回文串開始的地方),那麽方程為start[i]=max(start[i],start[i-2]-2) (-2是為了忽略插入的‘#‘號) ,以某個點為終點的長度同理,反向O(n)掃一遍就行了,最後再掃一遍統計答案,誒,好像就可以A了耶

#include<bits/stdc++.h>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<deque>
#include<list>
#include<set>
#include<vector>
#include<iostream>
#define
ll long long #define re register #define inf 0x3f3f3f3f #define inl inline #define sqr(x) (x*x) //#define eps 1e-8 #define debug printf("debug\n"); //#pragma comment(linker, "/STACK:1024000000,1024000000") //#pragma GCC optimize (2) //#pragma G++ optimize (2) using namespace std; //const ll mod; const ll MAXN=1e5+10
; inl ll read() { re ll x = 0; re int f = 1; char ch = getchar(); while(ch<0||ch>9) { if(ch== - ) f = -1; ch = getchar(); } while(ch>=0&&ch<=9) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x * f; } inl char readc() { char ch=getchar(); while((z<ch||ch<a)&&(Z<ch||ch<A)) ch=getchar(); return ch; } inl void write(re ll x){ if(x>=10)write(x/10); putchar(x%10+0); } inl void writeln(re ll x){ if(x<0) {x=-x;putchar(-);} write(x); puts(""); } inl ll gcd(re ll x,re ll y){while(y^=x^=y^=x%=y);return x;} inl void FR() { freopen(".in","r",stdin); freopen(".out","w",stdout); } inl void FC() { fclose(stdin); fclose(stdout); } char s[MAXN],ss[MAXN<<2]; ll n,nn,st[MAXN<<2],ed[MAXN<<2],hw[MAXN<<2]; void manacher() { ll mr=0,mid=0; for(re ll i=1;i<=nn;i++) { if(i<mr) hw[i]=min(hw[(mid<<1)-i],hw[mid]+mid-i); else hw[i]=1; while(ss[i+hw[i]]==ss[i-hw[i]]) hw[i]++; if(i+hw[i]>mr) {mr=i+hw[i];mid=i;} } } int main() { // FR(); scanf("%s",s+1);n=strlen(s+1); ss[0]=ss[1]=#;nn=n<<1|1; for(re ll i=1;i<=n;i++) { ss[i<<1]=s[i];ss[i<<1|1]=#; } manacher(); for(re ll i=1;i<=nn;i++) { ed[i+hw[i]-1]=max(ed[i+hw[i]-1],hw[i]-1); st[i-hw[i]+1]=max(st[i-hw[i]+1],hw[i]-1); } for(re ll i=1;i<=nn;i+=2) st[i]=max(st[i],st[i-2]-2); for(re ll i=nn;i>=1;i-=2) ed[i]=max(ed[i],ed[i+2]-2); re ll ans=0; for(re ll i=1;i<=nn;i+=2) { if(st[i]&&ed[i]) {ans=max(ans,st[i]+ed[i]);} } writeln(ans); // FC(); return 0; }

BZOJ2565 最長雙回文串 manacher