bzoj 3881 [Coci2015]Divljak——LCT维护parent树链并
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3881
对 S 建 SAM ,每个 T 会让 S 的 parent 树的链并答案+1;在 T 走每一步的时候,走到的节点用 LCT access 一下,就能找到该点到 parent 根的链。
给链打标记。在 access 的过程中,如果遇到已经打过这个 T 标记的点,就停止 access 。
注意实现的时候,在判断 fa[x] 有没有标记之前要先 splay(fa[x]) 。
#include<cstdio> #include<cstring> #include<algorithm> #define ls c[cr][0] #define rs c[cr][1] using namespace std; int rdn() { int ret=0;bool fx=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();} while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar(); return fx?ret:-ret; } const int N=1e5+5,M=2e6+5,K=26; int n,ps[N],tot=1,c[M][K],tc[M][K],fl[M],q[M]; int tim,dfn[M],fa[M],vl[M],tg[M],sta[M]; char s[M]; bool isrt(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;} void cz(int cr) { if(!tg[cr])return; int w=tg[cr];tg[cr]=0; vl[ls]+=w; vl[rs]+=w; tg[ls]+=w; tg[rs]+=w; dfn[ls]=dfn[rs]=dfn[cr];/// } void rotate(int x) { int y=fa[x],z=fa[y],d=(x==c[y][1]); if(!isrt(y))c[z][y==c[z][1]]=x; fa[x]=z; fa[y]=x; fa[c[x][!d]]=y; c[y][d]=c[x][!d]; c[x][!d]=y; } void splay(int x) { int top; sta[top=1]=x; for(int k=x;!isrt(k);k=fa[k])sta[++top]=fa[k]; for(int i=top;i;i--)cz(sta[i]); for(int y=fa[x],z=fa[y];!isrt(x);rotate(x),y=fa[x],z=fa[y]) if(!isrt(y)) ((y==c[z][0])^(x==c[y][0]))?rotate(x):rotate(y); } void access(int x) { splay(x); if(dfn[x]==tim)return; int t=0; while(1) { c[x][1]=t; if(!fa[x]) { tg[x]++;vl[x]++;dfn[x]=tim;return;} splay(fa[x]);//splay first if(dfn[fa[x]]==tim) { tg[x]++;vl[x]++;dfn[x]=tim;return;} t=x; x=fa[x]; } } void link(int x,int y){ fa[y]=x;} int Ins() { int cr=1,len=strlen(s+1); for(int i=1;i<=len;i++) { int w=s[i]-'a'; if(!tc[cr][w])tc[cr][w]=++tot; cr=tc[cr][w]; } return cr; } void get_fl() { int he=0,tl=0; for(int i=0,v;i<K;i++) if((v=tc[1][i])) {q[++tl]=v;fl[v]=1;link(1,v);} else tc[1][i]=1; while(he<tl) { int k=q[++he],pr=fl[k]; for(int i=0,v;i<K;i++) if((v=tc[k][i])) { q[++tl]=v;fl[v]=tc[pr][i];link(tc[pr][i],v);} else tc[k][i]=tc[pr][i]; } } void solve() { tim++; int cr=1,len=strlen(s+1); for(int i=1;i<=len;i++) { cr=tc[cr][s[i]-'a']; access(cr); } } int main() { n=rdn(); for(int i=1;i<=n;i++) { scanf("%s",s+1); ps[i]=Ins();} get_fl(); int Q=rdn(),op,x; while(Q--) { op=rdn(); if(op==1) { scanf("%s",s+1); solve();} else { x=rdn(); x=ps[x]; splay(x); printf("%d\n",vl[x]); } } return 0; }