1. 程式人生 > >【HDU5421】Victor and String(回文樹)

【HDU5421】Victor and String(回文樹)

fin void 發現 scanf oid sca print algo init

【HDU5421】Victor and String(回文樹)

題面

Vjudge
大意:
你需要支持以下操作:
動態在前端插入一個字符
動態在後端插入一個字符
回答當前本質不同的回文串個數
回答當前回文串個數

題解

回文樹前端插入的操作,學一學感覺並不難?
額外維護一下一個前端插入的\(last\)
然後就和後端插入一模一樣,前端插入時就是前端插入的\(last\)
唯一會產生的影響的就是當前字符差完後,
發現現在的\(last\)就是整個串,那麽就要更新另外一端的\(last\)為當前這一端的\(last\)

#include<iostream>
#include<cstdio>
#include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<set> #include<map> #include<vector> #include<queue> using namespace std; #define ll long long #define RG register #define MAX 222222 inline int read() { RG int x=0,t=1
;RG char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=-1,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return x*t; } struct Node { int son[26],ff; int len,dep; }t[MAX]; char
s[MAX]; ll ans; int tot,l,r,pre,suf,n; void init() { l=1e5,r=l-1;memset(s,'\0',sizeof(s)); memset(t,0,sizeof(t));ans=0; t[pre=suf=0].ff=t[tot=1].ff=1;t[1].len=-1; } void extend(int c,int n,int &last,int op) { int p=last; while(s[n]!=s[n-op*t[p].len-op])p=t[p].ff; if(!t[p].son[c]) { int v=++tot,k=t[p].ff;t[v].len=t[p].len+2; while(s[n]!=s[n-op*t[k].len-op])k=t[k].ff; t[v].ff=t[k].son[c];t[p].son[c]=v; t[v].dep=t[t[v].ff].dep+1; } last=t[p].son[c];ans+=t[last].dep; if(t[last].len==r-l+1)pre=suf=last; } int main() { while(scanf("%d",&n)!=EOF) { init(); while(n--) { int opt=read(); if(opt<=2) { char c=getchar(); if(opt==1)s[--l]=c,extend(c-97,l,pre,-1); else s[++r]=c,extend(c-97,r,suf,1); } else if(opt==3)printf("%d\n",tot-1); else printf("%lld\n",ans); } } return 0; }

【HDU5421】Victor and String(回文樹)