1. 程式人生 > >【字尾自動機】BZOJ5084[hashit]題解

【字尾自動機】BZOJ5084[hashit]題解

題目概述

給出一個操作串:如果是小寫字母,表示在當前字串後面新增這個小寫字母。如果是 ,表示刪除當前字串最後的小寫字母(保證合法)。求每次操作後當前字串不同子串的個數。

解題報告

不同子串個數是字尾自動機裸題,由於每次只刪除最後一個小寫字母,所以瞎搞就行了……

2018.5.20UPD:這樣複雜度是不對的,正解是字尾平衡樹,不過沒故意卡還是過了XD。

好像也可以後綴平衡樹?但是我不會QAQ。

示例程式

#include<cstdio>
#include<cstring>
#include<algorithm>
#define fr first
#define sc second #define mp make_pair using namespace std; typedef long long LL; const int maxl=100000,maxt=maxl<<1,maxi=26; int si,ro,p,son[maxt+5][maxi],fa[maxt+5],MAX[maxt+5];LL ans,v[maxl+5]; int now,A[maxl+5],B[maxl+5],P[maxl+5],pos;pair<int*,int> tem[maxt+5]; #define newnode(m) (A[now]++,fa[++si]=0,MAX[si]=m,memset(son[si],0,sizeof(son[si])),si)
#define val(p) (MAX[p]-MAX[fa[p]]) #define Add(x) (tem[++pos]=mp(&x,x),B[now]++) inline void Extend(int w){ now++;A[now]=B[now]=v[now]=0;P[now]=p; int np=newnode(MAX[p]+1);while (p&&!son[p][w]) Add(son[p][w]),son[p][w]=np,p=fa[p]; if (!p) fa[np]=ro; else{ int q=son[p][w]; if
(MAX[p]+1==MAX[q]) fa[np]=q; else{ int nq=newnode(MAX[p]+1);memcpy(son[nq],son[q],sizeof(son[q])); v[now]-=val(q);fa[nq]=fa[q];v[now]+=val(nq); Add(fa[q]);fa[np]=fa[q]=nq;v[now]+=val(q); while (p&&son[p][w]==q) Add(son[p][w]),son[p][w]=nq,p=fa[p]; } } v[now]+=val(np);ans+=v[now];p=np; } int main(){ freopen("program.in","r",stdin); freopen("program.out","w",stdout); for (char ch=(p=ro=newnode(0),getchar());'a'<=ch&&ch<='z'||ch=='-';ch=getchar()){ if ('a'<=ch&&ch<='z') Extend(ch-'a'); else{ for (int i=1;i<=B[now];i++,pos--) *tem[pos].fr=tem[pos].sc; si-=A[now];ans-=v[now];p=P[now];now--; } printf("%lld\n",ans); } return 0; }