BZOJ3926 ZJOI2015 广义后缀自动机
https://www.lydsy.com/JudgeOnline/problem.php?id=3926
CLJ老师题解
http://wjmzbmr.com/archives/zjoi-2015-day-1%E9%A2%98%E8%A7%A3/
对于树上的所有叶子节点领出来做Tire
再将所有Tire合并起来
再弄一个广义后缀自动机维护所有子串
ans=Σleni-lenfa[i]
#include<cstdio> #include<algorithm> #include<cstring> #define rep(i,s,t) for(register int i=s;i<=t;++i) #define _rep(i,s,t) for(register int i=s;i>=t;--i) #define Rep(i,s,t) for(register int i=s;i<t;++i) using namespace std; namespace IO{ #define gc getchar() #define pc(x) putchar(x) template<typename T>inline void read(T &x){ x=0;int f=1;char ch=gc; while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=gc;} while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=gc; x*=f;return; } template<typename T>inline void write(T x=0){ T wr[51];wr[0]=0; if(x<0)pc('-'),x=-x; if(!x)pc(48); while(x)wr[++wr[0]]=x%10,x/=10; while(wr[0])pc(48+wr[wr[0]--]); return; } } using IO::read; using IO::write; const int N=1e6+11; typedef long long ll; int t,x,y,tot,n,m; ll k; struct SAM{ int ch[N<<2][20],las,cnt,fa[N<<2],c[N<<2],pos[N<<2]; ll ans,l[N<<2]; SAM(){ las=cnt=1; } inline int add(int las,int c){ int np=++cnt,p=las;l[np]=l[p]+1; for(;p&&!ch[p][c];p=fa[p])ch[p][c]=np; if(!p)fa[np]=1; else{ int q=ch[p][c]; if(l[p]+1==l[q]) fa[np]=q; else{ int nq=++cnt;l[nq]=l[p]+1; memcpy(ch[nq],ch[q],sizeof ch[q]); fa[nq]=fa[q],fa[q]=fa[np]=nq; for(;ch[p][c]==q;p=fa[p])ch[p][c]=nq; } } return np; } inline void solve(){ _rep(i,cnt,1) ans+=l[i]-l[fa[i]]; printf("%lld\n",ans); } }sam; int v[N],las[N],to[N],nxt[N],deg[N]; inline void add(int x,int y){ nxt[++tot]=las[x],las[x]=tot,to[tot]=y,++deg[y]; } inline void dfs(int x,int fa,int p){ int T=sam.add(p,v[x]); for(register int e=las[x];e;e=nxt[e]) if(to[e]!=fa) dfs(to[e],x,T); } int main(){ read(n),read(m); rep(i,1,n) read(v[i]); rep(i,2,n) read(x),read(y), add(x,y),add(y,x); rep(i,1,n) if(deg[i]==1) dfs(i,0,1); sam.solve(); return 0; }