BZOJ4545: DQS的trie

BZOJ4545: DQS的trie

https://lydsy.com/JudgeOnline/problem.php?id=4545

分析:

  • 对trie用dfs建sam复杂度是\(O(n^2)\)的,因为你不能让一个复杂度带均摊的东西去一直回溯。
  • 构造数据卡也很好卡,一条链边全是a,每个点连出去一条不是a的边。
  • 于是我们用bfs建sam,这样复杂度是对的?
  • 说这道题的做法,第一个询问每次插入时动态维护即可,第二问操作我们用lct维护后缀链接树。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 400050
#define isrt(p) (ch[f[p]][1]!=p&&ch[f[p]][0]!=p)
typedef long long ll;
int ch[N][3],fa[N],len[N],cnt=1,pos[N],n;
ll nowans;
int head[N],to[N],nxt[N],CNT,val[N];
inline void add(int u,int v,int w) {
	to[++CNT]=v; nxt[CNT]=head[u]; head[u]=CNT; val[CNT]=w;
}
int tr[N];
struct LCT {
	#define ls ch[p][0]
	#define rs ch[p][1]
	#define get(x) (ch[f[x]][1]==x)
	int ch[N][2],tag[N],f[N];
	void rotate(int x) {
		int y=f[x],z=f[y],k=get(x);
		if(!isrt(y)) ch[z][ch[z][1]==y]=x;
		ch[y][k]=ch[x][!k]; f[ch[y][k]]=y;
		ch[x][!k]=y; f[y]=x; f[x]=z; 
	}
	inline void giv(int p,int d) {
		tag[p]+=d; tr[p]+=d;
	}
	inline void pushdown(int p) {
		if(tag[p]) {
			if(ls) giv(ls,tag[p]);
			if(rs) giv(rs,tag[p]);
			tag[p]=0;
		}
	}
	void UPD(int p) {
		if(!isrt(p)) UPD(f[p]);
		pushdown(p);
	}
	void splay(int x) {
		UPD(x);
		for(int d;d=f[x],!isrt(x);rotate(x)) {
			if(!isrt(d)) rotate(get(x)==get(d)?d:x);
		}
	}
	void access(int p) {
		int t=0;
		while(p) {
			splay(p); rs=t; t=p; p=f[p];
		}
	}
	void cut(int p) {
		access(p); splay(p); f[ls]=0; ls=0;
	}
	void link(int p,int q) {
		f[p]=q;
	}
}_;
int insert(int x,int lst) {
	int p=lst,np,q,nq;
	np=++cnt; lst=np;
	len[np]=len[p]+1;
	for(;p&&!ch[p][x];p=fa[p]) ch[p][x]=np;
	if(!p) fa[np]=1,nowans+=len[np],_.link(np,1);
	else {
		q=ch[p][x];
		if(len[q]==len[p]+1) fa[np]=q,nowans+=len[np]-(len[fa[np]]),_.link(np,q);
		else {
			nq=++cnt;
			len[nq]=len[p]+1;
			memcpy(ch[nq],ch[q],sizeof(ch[q]));
			_.UPD(q); tr[nq]=tr[q];
			nowans-=(len[q]-len[fa[q]]);
			fa[nq]=fa[q]; 
			_.link(nq,fa[q]); 

			fa[q]=fa[np]=nq;
			_.cut(q); _.link(q,nq); _.link(np,nq);
			nowans+=(len[q]-len[fa[q]])+(len[nq]-len[fa[nq]])+(len[np]-len[fa[np]]);

			for(;p&&ch[p][x]==q;p=fa[p]) ch[p][x]=nq;
		}
	}
	_.access(lst), _.splay(lst), _.giv(lst,1);
	return lst;
}
int Q[N];
bool vis[N];
void bfs(int x) {
	int i,l=0,r=0;
	Q[r++]=x; vis[x]=1;
	while(l<r) {
		x=Q[l++];
		for(i=head[x];i;i=nxt[i]) if(!vis[to[i]]) {
			vis[to[i]]=1; pos[to[i]]=insert(val[i],pos[x]); Q[r++]=to[i];
		}
	}
}
char w[N];
int main() {
	scanf("%*d%d",&n);
	int i,x,y;
	pos[1]=1;
	char oo[10];
	for(i=1;i<n;i++) {
		scanf("%d%d%s",&x,&y,oo+1);
		add(x,y,oo[1]-'a'),add(y,x,oo[1]-'a');
	}
	bfs(1);
	int m;
	scanf("%d",&m);
	int sz;
	while(m--) {
		int opt;
		scanf("%d",&opt);
		if(opt==1) {
			printf("%lld\n",nowans);
		}else if(opt==2) {
			int rt;
			scanf("%d%d",&rt,&sz); head[rt]=0;
			for(i=1;i<sz;i++) {
				scanf("%d%d%s",&x,&y,oo+1);
				add(x,y,oo[1]-'a'), add(y,x,oo[1]-'a');
			}
			bfs(rt);
		}else {
			scanf("%s",w+1);
			int k=strlen(w+1),p=1;
			for(i=1;i<=k;i++) {
				x=w[i]-'a';
				if(ch[p][x]) p=ch[p][x];
				else {p=ch[p][x]; break;}
			}
			if(!p) {puts("0");continue ;}
			_.splay(p); 
			printf("%d\n",tr[p]);
		}
	}
}
posted @ 2018-12-01 21:59  fcwww  阅读(509)  评论(0编辑  收藏  举报