1. 程式人生 > >bzoj4516: [Sdoi2016]生成魔咒(SAM)

bzoj4516: [Sdoi2016]生成魔咒(SAM)

www. AD void long == map type oot online

4516: [Sdoi2016]生成魔咒

題目:傳送門


題解:

   真奧義之SAM裸題...

   其實對於當前新增節點x的操作,每次對ans的貢獻就是dep[x]-dep[fail[x]](根據fail指針的定義隨便YY)

   然後有思路之後乍看題目每個x是10^9...瞬間GG

   %了已發cc然後被D飛,直接上map啊

  


代碼:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<cmath>
 5
#include<algorithm> 6 #include<map> 7 using namespace std; 8 typedef long long LL; 9 int a[110000],root,last,cnt,n; 10 LL ans; 11 map<int,int>ch[210000]; 12 int fail[210000],dep[210000]; 13 void add(int k) 14 { 15 int x=a[k]; 16 int p=last,np=++cnt;dep[np]=k; 17 while(p && ch[p][x]==0
)ch[p][x]=np,p=fail[p]; 18 if(p==0)fail[np]=root,ans+=LL(dep[np]); 19 else 20 { 21 int q=ch[p][x]; 22 if(dep[q]==dep[p]+1)fail[np]=q,ans+=LL(dep[np]-dep[q]); 23 else 24 { 25 int nq=++cnt;dep[nq]=dep[p]+1; 26 ch[nq]=ch[q];fail[nq]=fail[q];
27 fail[q]=fail[np]=nq; 28 while(p && ch[p][x]==q)ch[p][x]=nq,p=fail[p]; 29 ans+=LL(dep[np]-dep[nq]); 30 } 31 } 32 last=np; 33 } 34 int main() 35 { 36 scanf("%d",&n);ans=0; 37 cnt=0;root=last=++cnt; 38 for(int i=1;i<=n;i++) 39 { 40 scanf("%d",&a[i]);add(i); 41 printf("%lld\n",ans); 42 } 43 return 0; 44 }

bzoj4516: [Sdoi2016]生成魔咒(SAM)