1. 程式人生 > >bzoj4566 [Haoi2016]找相同字符

bzoj4566 [Haoi2016]找相同字符

efi truct fin ive build 不用 子串和 答案 ans

Description

給定兩個字符串,求出在兩個字符串中各取出一個子串使得這兩個子串相同的方案數。兩個方案不同當且僅當這兩個子串中有一個位置不同。

Input

兩行,兩個字符串s1,s2,長度分別為n1,n2。1 <=n1, n2<= 200000,字符串中只有小寫字母

Output

輸出一個整數表示答案

Sample Input

aabb
bbaa

Sample Output

10 正解:後綴自動機+後綴樹。 做完以後看網上的題解,才發現我的做法是最笨的。。 這道題前綴和後綴一樣,所以我們可以不用反向構後綴自動機了。 然後我的$naive$做法是先在兩個串中間弄一個分隔符,然後再對這個大串構一個後綴自動機,算出貢獻。 但是這樣會算重,具體來說就是一個子串和它自己那個串中的子串算了一次答案。 於是我們再對兩個小串分別構後綴自動機,減去相應貢獻就行了。
  1
#include <bits/stdc++.h> 2 #define il inline 3 #define RG register 4 #define ll long long 5 6 using namespace std; 7 8 char s1[200010],s2[200010]; 9 int len1,len2; 10 ll ans; 11 12 il int gi(){ 13 RG int x=0,q=1; RG char ch=getchar(); 14 while ((ch<0 || ch>
9) && ch!=-) ch=getchar(); 15 if (ch==-) q=-1,ch=getchar(); 16 while (ch>=0 && ch<=9) x=x*10+ch-48,ch=getchar(); 17 return q*x; 18 } 19 20 struct Big_Suffix_Automaton{ 21 22 #define N (800010) 23 24 struct edge{ int nt,to; }g[N]; 25 26
int ch[N][27],fa[N],sz[N],l[N],head[N],la,tot,num; 27 28 il void init(){ la=++tot; return; } 29 30 il void add(RG int c){ 31 RG int np=++tot,p=la; la=np,l[np]=l[p]+1,sz[np]=1; 32 for (;p && !ch[p][c];p=fa[p]) ch[p][c]=np; 33 if (!p){ fa[np]=1; return; } RG int q=ch[p][c]; 34 if (l[q]==l[p]+1) fa[np]=q; else{ 35 RG int nq=++tot; l[nq]=l[p]+1; 36 fa[nq]=fa[q],fa[q]=fa[np]=nq; 37 memcpy(ch[nq],ch[q],sizeof(ch[q])); 38 for (;ch[p][c]==q;p=fa[p]) ch[p][c]=nq; 39 } 40 return; 41 } 42 43 il void insert(RG int from,RG int to){ 44 g[++num]=(edge){head[from],to},head[from]=num; return; 45 } 46 47 il void build(){ 48 for (RG int i=2;i<=tot;++i) insert(fa[i],i); 49 return; 50 } 51 52 il void dfs(RG int x,RG int fg){ 53 for (RG int i=head[x],v;i;i=g[i].nt){ 54 v=g[i].to,dfs(v,fg); 55 ans+=1LL*fg*l[x]*sz[x]*sz[v],sz[x]+=sz[v]; 56 } 57 return; 58 } 59 60 #undef N 61 62 }SAM0; 63 64 struct Small_Suffix_Automaton{ 65 66 #define N (400010) 67 68 struct edge{ int nt,to; }g[N]; 69 70 int ch[N][27],fa[N],sz[N],l[N],head[N],la,tot,num; 71 72 il void init(){ la=++tot; return; } 73 74 il void add(RG int c){ 75 RG int np=++tot,p=la; la=np,l[np]=l[p]+1,sz[np]=1; 76 for (;p && !ch[p][c];p=fa[p]) ch[p][c]=np; 77 if (!p){ fa[np]=1; return; } RG int q=ch[p][c]; 78 if (l[q]==l[p]+1) fa[np]=q; else{ 79 RG int nq=++tot; l[nq]=l[p]+1; 80 fa[nq]=fa[q],fa[q]=fa[np]=nq; 81 memcpy(ch[nq],ch[q],sizeof(ch[q])); 82 for (;ch[p][c]==q;p=fa[p]) ch[p][c]=nq; 83 } 84 return; 85 } 86 87 il void insert(RG int from,RG int to){ 88 g[++num]=(edge){head[from],to},head[from]=num; return; 89 } 90 91 il void build(){ 92 for (RG int i=2;i<=tot;++i) insert(fa[i],i); 93 return; 94 } 95 96 il void dfs(RG int x,RG int fg){ 97 for (RG int i=head[x],v;i;i=g[i].nt){ 98 v=g[i].to,dfs(v,fg); 99 ans+=1LL*fg*l[x]*sz[x]*sz[v],sz[x]+=sz[v]; 100 } 101 return; 102 } 103 104 #undef N 105 106 }SAM1,SAM2; 107 108 int main(){ 109 #ifndef ONLINE_JUDGE 110 freopen("same.in","r",stdin); 111 freopen("same.out","w",stdout); 112 #endif 113 scanf("%s%s",s1+1,s2+1); 114 len1=strlen(s1+1),len2=strlen(s2+1); 115 SAM0.init(),SAM1.init(),SAM2.init(); 116 for (RG int i=1;i<=len1;++i) 117 SAM0.add(s1[i]-a),SAM1.add(s1[i]-a); 118 SAM0.add(26); 119 for (RG int i=1;i<=len2;++i) 120 SAM0.add(s2[i]-a),SAM2.add(s2[i]-a); 121 SAM0.build(),SAM1.build(),SAM2.build(); 122 SAM0.dfs(1,1),SAM1.dfs(1,-1),SAM2.dfs(1,-1); 123 cout<<ans; return 0; 124 }

bzoj4566 [Haoi2016]找相同字符