这是个后缀平衡树的裸题。。。。
然后傻逼的我调了一下午。
#include<bits/stdc++.h> typedef long long ll; using namespace std; const int N=1e5+10; const int bas=31; int hs[N],M[N]; int n,len,ans,Ans[N]; inline int read(){ int f=1,x=0;char ch; do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9'); do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9'); return f*x; } struct Suffix_Balanced_ScapeGoat_Tree{ int lx[N],rx[N],rt,size[N],s[N],cnt,Q[N],tail; ll tag[N]; int get(int i,int l){return hs[i]-hs[i-l]*M[l];} int qlcp(int x,int y){ int l=0,r=min(x,y); while(l<r){ int mid=(l+r)>>1; if(get(x,mid+1)==get(y,mid+1))l=mid+1;else r=mid; } return l; } inline bool cmp(int x,int y){int l=qlcp(x,y);return s[x-l]<s[y-l];} inline int merge(int x,int y){ if(!x||!y)return x|y; if(size[x]>size[y]){size[x]+=size[y];rx[x]=merge(rx[x],y);return x;} else{size[y]+=size[x];lx[y]=merge(x,lx[y]);return y;} } inline int build(int ls,int rs,ll l,ll r){ if(ls>rs)return 0; int mid=(ls+rs)>>1;ll midv=(l+r)>>1;int x=Q[mid];tag[x]=midv; lx[x]=build(ls,mid-1,l,midv);rx[x]=build(mid+1,rs,midv,r); size[x]=rs-ls+1;return x; } inline void dfs(int x){if(lx[x])dfs(lx[x]);Q[++tail]=x;if(rx[x])dfs(rx[x]);} inline int rebuild(int x,ll l,ll r){ tail=0;dfs(x);return build(1,tail,l,r); } inline int ins(int x,ll l,ll r,int val){ if(!x){ size[++cnt]=1;lx[cnt]=rx[cnt]=0;tag[cnt]=(l+r)>>1; return cnt; } size[x]++; if(cmp(x,val)){ rx[x]=ins(rx[x],tag[x],r,val); if(size[rx[x]]>0.65*size[x])x=rebuild(x,l,r); } else{ lx[x]=ins(lx[x],l,tag[x],val); if(size[lx[x]]>0.65*size[x])x=rebuild(x,l,r); } return x; } inline int del(int x,int val){ if(x==val)return merge(lx[x],rx[x]); size[x]--; if(tag[x]<tag[val])rx[x]=del(rx[x],val); else lx[x]=del(lx[x],val); return x; } inline int queryrk(int key){ int x=rt,ans=0; while(1){ int i=size[lx[x]]+1; if(key==x)return ans+i; if(tag[x]<tag[key])x=rx[x],ans+=i;else x=lx[x]; } } inline int find(int key){ int x=rt; while(1){ int i=size[lx[x]]+1; if(key==i)return x; if(key>i)x=rx[x],key-=i;else x=lx[x]; } } inline void del(int x){ int rk=queryrk(x),y=find(rk-1),z=find(rk+1); ans-=qlcp(x,y)+qlcp(x,z)-qlcp(y,z); rt=del(rt,x);cnt--;len--; } inline void ins(int x){ s[++len]=x;hs[len]=hs[len-1]*bas+x; rt=ins(rt,0,1LL<<62,len); if(len<3)return; int rk=queryrk(len),y=find(rk-1),z=find(rk+1); ans+=qlcp(len,y)+qlcp(len,z)-qlcp(y,z); } }T; char str[N]; struct Edge{int u,v,next;}G[N<<1];int head[N],tot=0; inline void addedge(int u,int v){ G[++tot].u=u;G[tot].v=v;G[tot].next=head[u];head[u]=tot; G[++tot].u=v;G[tot].v=u;G[tot].next=head[v];head[v]=tot; } inline void dfs(int u,int fa){ T.ins(str[u]-'a'+1);Ans[u]=(len-1)*(len-2)/2-ans; for(int i=head[u];i;i=G[i].next){ if(G[i].v!=fa)dfs(G[i].v,u); } T.del(len); } int main(){ freopen("balsuffix.in","r",stdin); freopen("balsuffix.out","w",stdout); M[0]=1; for(int i=1;i<N;i++)M[i]=M[i-1]*bas; T.ins(27);T.ins(0);int T=read(); while(T--){ n=read();for(int i=1;i<=n;i++)head[i]=0;tot=0; for(int i=1;i<n;i++){ int u=read(),v=read();addedge(u,v); } scanf("%s",str+1); dfs(1,0); for(int i=1;i<=n;i++)printf("%d ",Ans[i]); } }