1. 程式人生 > >USACO18DEC Platinum

USACO18DEC Platinum

out open bsp ret and 前綴 main AS src

standing out from the field

給你n個串,對於每個串求出只包含在這個串中的本質不同的子串?

後綴自動機,建樹,對於每一個點打上包含在哪個串中的標記。

葉子都是前綴,直接在sam_build時預處理;其余的dfs一遍,由於x是son[x]的後綴,故x的狀態由son[x]影響,如果son[x]有出現在不同串中的,標記x為-1。

技術分享圖片
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int N=200005;
 5 char s[N+1];
 6 int
last,sc,p,np,l[N],son[N][26],fa[N],cnt,head[N],f[N]; 7 ll ans[N]; 8 struct node{int to,next;}num[N]; 9 void add(int x,int y) 10 {num[++cnt].to=y;num[cnt].next=head[x];head[x]=cnt;} 11 void Sam(int c,int id) 12 { 13 p=last; np=last=++sc; l[np]=l[p]+1; 14 for (;p&&!son[p][c];p=fa[p]) son[p][c]=np;
15 if (!p) fa[np]=1; 16 else { 17 int q=son[p][c]; 18 if (l[p]+1==l[q]) fa[np]=q; 19 else { 20 int nq=++sc; l[nq]=l[p]+1; 21 memcpy(son[nq],son[q],sizeof(son[q])); 22 fa[nq]=fa[q];fa[q]=fa[np]=nq; 23 for (;son[p][c]==q;p=fa[p]) son[p][c]=nq;
24 } 25 } 26 if (f[np]&&f[np]!=id) f[np]=-1;else f[np]=id;//處理葉子及一部分為前綴的非葉子 27 } 28 void dfs(int x) 29 { 30 for (int i=head[x];i;i=num[i].next) 31 if (num[i].to!=fa[x]) dfs(num[i].to); 32 if (f[x]&&f[x]!=-1) ans[f[x]]+=l[x]-l[fa[x]]; 33 if (f[fa[x]]&&f[fa[x]]!=f[x]) f[fa[x]]=-1;else f[fa[x]]=f[x]; 34 } 35 int main() 36 { 37 int T;scanf("%d",&T); 38 sc=1; 39 for (int i=1;i<=T;i++) 40 { 41 scanf("%s",s+1); int sl=strlen(s+1); 42 last=1; 43 for (int j=1;j<=sl;j++) Sam(s[j]-a,i); 44 } 45 for (int i=2;i<=sc;i++) add(fa[i],i); 46 dfs(1); 47 for (int i=1;i<=T;i++) printf("%lld\n",ans[i]); 48 return 0; 49 }
View Code

USACO18DEC Platinum