BZOJ3926 諸神眷顧的幻想鄉
阿新 • • 發佈:2018-12-22
傳送門
樹上SAM!
顯然如果樹上一條一條字串放的話那麼是n^2的w
但是 題目的性質非常吼啊!
20個葉子節點 我們就可以 把所有葉子結點拎出來當根 全部扔到一個SAM裡 就吼啦
最後的答案是 因為自動機上一個節點的貢獻就是這麼多啦
自動機啥的程式碼真的好寫呢[FLAG]
(機房好冷啊)
附程式碼。
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define inf 20021225 #define ll long long #define mxn 100010 using namespace std; struct edge{int to,lt;}e[mxn<<1]; struct node{int ch[10],fa,len;}t[mxn*63]; int pos[mxn],rt,poi,d[mxn],in[mxn]; int val[mxn],n,cnt; void init() { memset(pos,0,sizeof(pos)); pos[0]=1; } void add(int x,int y) { e[++cnt].to=y;e[cnt].lt=in[x];in[x]=cnt;d[x]++; e[++cnt].to=x;e[cnt].lt=in[y];in[y]=cnt;d[y]++; } void insert(int id,int lt) { int p=lt,c=val[id]; int np=pos[id]=++poi; t[np].len=t[p].len+1; for(;p&&!t[p].ch[c];p=t[p].fa) t[p].ch[c]=np; if(!p){t[np].fa=rt;return;} int q=t[p].ch[c]; if(t[q].len==t[p].len+1){t[np].fa=q;return;} int nq=++poi; t[nq].len=t[p].len+1; memcpy(t[nq].ch,t[q].ch,sizeof(t[q].ch)); t[nq].fa=t[q].fa; t[q].fa=t[np].fa=nq; for(;p&&t[p].ch[c]==q;p=t[p].fa) t[p].ch[c]=nq; } void dfs(int x,int fa) { insert(x,pos[fa]); for(int i=in[x];i;i=e[i].lt) { int y=e[i].to;if(y==fa) continue; dfs(y,x); } } ll ans; void calc() { for(int i=poi;~i;i--) ans+=(ll)t[i].len-t[t[i].fa].len; } int main() { rt=++poi;int c,x,y; scanf("%d%d",&n,&c); for(int i=1;i<=n;i++) scanf("%d",&val[i]); for(int i=1;i<n;i++) scanf("%d%d",&x,&y),add(x,y); for(int i=1;i<=n;i++) if(d[i]==1) init(),dfs(i,0); calc(); printf("%lld\n",ans); return 0; }