luogu P4248 [AHOI2013]差異
阿新 • • 發佈:2018-12-16
其實要求的東西就是字尾樹上所有葉子對的距離之和.構建反串SAM,然後構建parent樹(原串字尾樹),然後就是樹型dp的事,具體細節留給讀者自行思考
那個,不會看程式碼啊
#include<bits/stdc++.h> #define LL long long #define il inline #define re register #define db double using namespace std; const int N=1000000+10; il LL rd() { LL x=0,w=1;char ch=0; while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();} while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();} return x*w; } int to[N],nt[N],hd[N],tot; il void add(int x,int y){++tot,to[tot]=y,nt[tot]=hd[x],hd[x]=tot;} char cc[N]; int n,bk[N>>1]; int fa[N],ch[N][26],la=1,tt=1; LL len[N],sz[N],sm[N],ans; il void inst(char c) { int np=++tt,p=la; la=np,sz[np]=1,len[np]=len[p]+1; while(p&&!ch[p][c-'a']) ch[p][c-'a']=np,p=fa[p]; if(!p) fa[np]=1; else { int q=ch[p][c-'a']; if(len[q]==len[p]+1) fa[np]=q; else { int nq=++tt; fa[nq]=fa[q],len[nq]=len[p]+1,fa[q]=fa[np]=nq; for(int i=0;i<26;++i) ch[nq][i]=ch[q][i]; while(p&&ch[p][c-'a']==q) ch[p][c-'a']=nq,p=fa[p]; } } } void dd(int x) { for(int i=hd[x];i;i=nt[i]) { int y=to[i]; dd(y),sz[x]+=sz[y],sm[x]+=sm[y]+(len[y]-len[x])*sz[y]; } for(int i=hd[x];i;i=nt[i]) { int y=to[i]; ans+=(sm[y]+(len[y]-len[x])*sz[y])*(sz[x]-sz[y]); } } int main() { scanf("%s",cc+1); n=strlen(cc+1); for(int i=1;i<=n;++i) inst(cc[n-i+1]); for(int i=2;i<=tt;++i) add(fa[i],i); dd(1); printf("%lld\n",ans); return 0; }