1. 程式人生 > >bzoj3238 [Ahoi2013]差異

bzoj3238 [Ahoi2013]差異

機構 char mem tchar 分享 har .com c++ include

Description

技術分享

Input

一行,一個字符串S

Output

一行,一個整數,表示所求值

Sample Input

cacao

Sample Output

54

HINT

2<=N<=500000,S由小寫英文字母組成

正解:後綴自動機+後綴樹。

這題就是用後綴自動機構造後綴樹,然後就很簡單了。

有一個性質,反串的後綴自動機構成的$parent$樹就是後綴樹。

然後我們構造出後綴樹以後,就可以直接樹形$dp$求出答案了。

另外註意,後綴自動機中新建的結點是不能算進方案中的,因為它並不是後綴結點。

 1
#include <bits/stdc++.h> 2 #define il inline 3 #define RG register 4 #define ll long long 5 #define N (1000010) 6 7 using namespace std; 8 9 struct edge{ int nt,to; }g[N]; 10 11 int ch[N][26],head[N],fa[N],sz[N],l[N],la,tot,len,num; 12 char s[N]; 13 ll ans; 14 15 il int gi(){
16 RG int x=0,q=1; RG char ch=getchar(); 17 while ((ch<0 || ch>9) && ch!=-) ch=getchar(); 18 if (ch==-) q=-1,ch=getchar(); 19 while (ch>=0 && ch<=9) x=x*10+ch-48,ch=getchar(); 20 return q*x; 21 } 22 23 il void insert(RG int from,RG int to){ 24 g[++num]=(edge){head[from
],to},head[from]=num; return; 25 } 26 27 il void add(RG int c){ 28 RG int p=la,np=++tot; la=np,l[np]=l[p]+1,sz[np]=1; 29 for (;p && !ch[p][c];p=fa[p]) ch[p][c]=np; 30 if (!p){ fa[np]=1; return; } RG int q=ch[p][c]; 31 if (l[q]==l[p]+1) fa[np]=q; else{ 32 RG int nq=++tot; l[nq]=l[p]+1; 33 fa[nq]=fa[q],fa[q]=fa[np]=nq; 34 memcpy(ch[nq],ch[q],sizeof(ch[q])); 35 for (;ch[p][c]==q;p=fa[p]) ch[p][c]=nq; 36 } 37 return; 38 } 39 40 il void dfs(RG int x){ 41 for (RG int i=head[x],v;i;i=g[i].nt){ 42 v=g[i].to,dfs(g[i].to); 43 ans+=1LL*sz[x]*sz[v]*l[x],sz[x]+=sz[v]; 44 } 45 return; 46 } 47 48 int main(){ 49 #ifndef ONLINE_JUDGE 50 freopen("difference.in","r",stdin); 51 freopen("difference.out","w",stdout); 52 #endif 53 scanf("%s",s+1),len=strlen(s+1),tot=la=1; 54 for (RG int i=len;i;--i) add(s[i]-a); 55 for (RG int i=2;i<=tot;++i) insert(fa[i],i); 56 dfs(1),cout<<1LL*(len-1)*len*(len+1)/2-2*ans; return 0; 57 }

bzoj3238 [Ahoi2013]差異