BZOJ5084: hashit
BZOJ5084: hashit
https://lydsy.com/JudgeOnline/problem.php?id=5084
分析:
- 对\(trie\)建立广义后缀自动机,由于是\(trie\),不会有多余结点(lenx==lenfa)
- 令后缀自动机结点权值为\(len_x-len _ {fa_x}\)。
- 每次询问时答案就等于所有结点到根的树链的并的权值和。
- 每次是插入一个点,删除一个点,用\(set\)动态维护即可。
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <set>
using namespace std;
typedef long long ll;
#define N 100050
#define db(x) cerr<<#x<<" = "<<x<<endl
char opt[N];
int n;
struct Trie {
int ch[N][26],cnt,fa[N];
void init() {cnt=1;}
void Wk() {
init();
int i,p=1;
for(i=1;i<=n;i++) {
if(opt[i]=='-') {
p=fa[p];
}else {
int &q=ch[p][opt[i]-'a'];
if(!q) q=++cnt,fa[q]=p;
p=q;
}
}
}
}t1;
struct Sam {
#undef N
#define N 200050
int ch[N][26],fa[N],len[N],cnt,Q[N],Lst[N];
int ke[N],ro[N],f[20][N],Lg[N],dep[N],w[N];
ll dis[N];
int head[N],to[N],nxt[N],tot,dfn[N];
inline void add(int u,int v) {
to[++tot]=v; nxt[tot]=head[u]; head[u]=tot;
}
void dfs(int x) {
int i; dfn[x]=++dfn[0];
for(i=head[x];i;i=nxt[i]) {
dep[to[i]]=dep[x]+1;
w[to[i]]=len[to[i]]-len[x];
dis[to[i]]=dis[x]+w[to[i]];
dfs(to[i]);
}
}
void init() {cnt=1;}
int insert(int x,int lst) {
int p=lst,np=++cnt,q,nq;
len[np]=len[p]+1; lst=np;
for(;p&&!ch[p][x];p=fa[p]) ch[p][x]=np;
if(!p) fa[np]=1;
else {
q=ch[p][x];
if(len[q]==len[p]+1) fa[np]=q;
else {
nq=++cnt;
len[nq]=len[p]+1; fa[nq]=fa[q]; memcpy(ch[nq],ch[q],sizeof(ch[q]));
fa[np]=fa[q]=nq;
for(;p&&ch[p][x]==q;p=fa[p]) ch[p][x]=nq;
}
}return lst;
}
int lca(int x,int y) {
int i;
if(dep[x]<dep[y]) swap(x,y);
for(i=Lg[dep[x]];i>=0;i--) {
if(dep[f[i][x]]>=dep[y]) x=f[i][x];
}if(x==y) return x;
for(i=Lg[dep[x]];i>=0;i--) {
if(f[i][x]!=f[i][y]) x=f[i][x],y=f[i][y];
}return f[0][x];
}
struct A {
int x,v;
bool operator < (const A &u) const {return v<u.v;}
};
set<A>S;
set<A>::iterator it;
ll nowans;
void fadd(int p) {
A t=(A){p,dfn[p]};
nowans+=dis[p];
it=S.upper_bound(t);
int x=0,y=0;
if(it!=S.end()) {
y=it->x;
}
if(it!=S.begin()) {
it--;
x=it->x;
}
if(x) nowans-=dis[lca(x,p)];
if(y) nowans-=dis[lca(y,p)];
if(x&&y) nowans+=dis[lca(x,y)];
S.insert(t);
}
void fdel(int p) {
A t=(A){p,dfn[p]};
S.erase(t);
nowans-=dis[p];
it=S.upper_bound(t);
int x=0,y=0;
if(it!=S.end()) {
y=it->x;
}
if(it!=S.begin()) {
it--;
x=it->x;
}
if(x) nowans+=dis[lca(x,p)];
if(y) nowans+=dis[lca(y,p)];
if(x&&y) nowans-=dis[lca(x,y)];
}
void Wk() {
init();
int p,i,j;
int l=0,r=0;
Q[r++]=1; Lst[1]=1;
while(l<r) {
p=Q[l++];
for(i=0;i<26;i++) if(t1.ch[p][i]) {
int q=t1.ch[p][i];
Lst[q]=insert(i,Lst[p]);
Q[r++]=q;
}
}
Lg[0]=-1;
for(i=1;i<=cnt;i++) f[0][i]=fa[i],Lg[i]=Lg[i>>1]+1;
for(i=1;(1<<i)<=cnt;i++) {
for(j=1;j<=cnt;j++) f[i][j]=f[i-1][f[i-1][j]];
}
for(i=2;i<=cnt;i++) add(fa[i],i);
dfs(1);
p=1;
for(i=1;i<=n;i++) {
if(opt[i]=='-') {
fdel(Lst[p]);
p=t1.fa[p];
printf("%lld\n",nowans);
}else {
p=t1.ch[p][opt[i]-'a'];
fadd(Lst[p]);
printf("%lld\n",nowans);
}
}
}
}t2;
int main() {
scanf("%s",opt+1);
n=strlen(opt+1);
t1.Wk();
t2.Wk();
}