bzoj 5084 hashit

LINK:hashit

动态在末尾删除一个节点或者加入一个节点 求每次操作过后本质不同的子串的个数。

显然我们可以离线,当然我们发现删除末尾的节点也是比较困难的 可以选择不删而是返回到last.

发现这样做其实是一颗trie树 我们建立广义SAM.

每次加入节点 其实是parent树上一堆链的并的答案。(不明白可以画一下样例的图即可。

我们将操作离线后使用常规set维护dfs序解决。

const int MAXN=200010;
int n,cnt=1,last=1,v,len;
struct wy
{
	int fa,len;
	int ch[26];
}t[MAXN];
int f[MAXN][20],d[MAXN],Log[MAXN],pre[MAXN],dfn[MAXN],pos[MAXN];
int lin[MAXN],ver[MAXN],nex[MAXN];
char a[MAXN];
set<int>s;
set<int>::iterator it;
inline void add(int x,int y)
{
	ver[++len]=y;
	nex[len]=lin[x];
	lin[x]=len;
}
inline int insert(int x)
{
	int p=last;
	if(t[p].ch[x])
	{
		int q=t[p].ch[x];
		if(len(q)==len(p)+1)return last=q;
		int nq=++cnt;
		t[nq]=t[q];
		f(q)=nq;
		len(nq)=len(p)+1;
		while(p&&t[p].ch[x]==q)
		{
			t[p].ch[x]=nq;
			p=f(p);
		}
		return last=nq;
	}
	int np=last=++cnt;
	len(np)=len(p)+1;
	while(p&&!t[p].ch[x])
	{
		t[p].ch[x]=np;
		p=f(p);
	}
	if(!p)f(np)=1;
	else
	{
		int q=t[p].ch[x];
		if(len(q)==len(p)+1)f(np)=q;
		else 
		{
			int nq=++cnt;
			t[nq]=t[q];
			f(q)=f(np)=nq;
			len(nq)=len(p)+1;
			while(p&&t[p].ch[x]==q)
			{
				t[p].ch[x]=nq;
				p=f(p);
			}
		}
	}
	return last;
}
inline void dfs(int x,int father)
{
	f[x][0]=father;d[x]=d[father]+1;dfn[x]=++v;pos[v]=x;
	rep(1,Log[d[x]],i)f[x][i]=f[f[x][i-1]][i-1];
	go(x)dfs(tn,x);return;
}
inline int LCA(int x,int y)
{
	if(d[x]<d[y])swap(x,y);
	for(int i=Log[d[x]];i>=0;--i)
		if(d[f[x][i]]>=d[y])x=f[x][i];
	if(x==y)return x;
	for(int i=Log[d[x]];i>=0;--i)
		if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
	return f[x][0];
}
int main()
{
	freopen("1.in","r",stdin);
	gc(a);n=strlen(a+1);ll ans=0;
	rep(1,n,i)
	{
		if(a[i]=='-')last=pre[last];
		else
		{
			int w=last;
			insert(a[i]-'a');pre[last]=w;
		}
	}
	rep(2,cnt,i)add(f(i),i),Log[i]=Log[i>>1]+1;
	dfs(1,0);int now=1;
	for(int i=1;i<=n;++i)
	{
		if(a[i]=='-')
		{
			ans-=len(now);it=s.find(dfn[now]);
			int x=0,y=0;++it;
			if(it!=s.end())x=pos[*it];
			--it;
			if(it!=s.begin())y=pos[*--it];
			if(x)ans+=len(LCA(x,now));
			if(y)ans+=len(LCA(y,now));
			if(x&&y)ans-=len(LCA(x,y));
			s.erase(dfn[now]);now=pre[now];
		}
		else
		{
			now=t[now].ch[a[i]-'a'];ans+=len(now);
			it=s.upper_bound(dfn[now]);
			int x=0,y=0;
			if(it!=s.end())y=pos[*it];
			if(it!=s.begin())x=pos[*--it];
			if(x)ans-=len(LCA(x,now));
			if(y)ans-=len(LCA(y,now));
			if(x&&y)ans+=len(LCA(x,y));
			s.insert(dfn[now]);
		}
		put(ans);
	}
	return 0;
}
posted @ 2020-03-24 13:36  chdy  阅读(115)  评论(0编辑  收藏  举报