【字尾自動機】BZOJ5084[hashit]題解
阿新 • • 發佈:2019-01-10
題目概述
給出一個操作串:如果是小寫字母,表示在當前字串後面新增這個小寫字母。如果是 ,表示刪除當前字串最後的小寫字母(保證合法)。求每次操作後當前字串不同子串的個數。
解題報告
不同子串個數是字尾自動機裸題,由於每次只刪除最後一個小寫字母,所以瞎搞就行了……
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;
}