bzoj4566 [Haoi2016]找相同字符

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 }

 

posted @ 2017-10-06 21:55  wfj_2048  阅读(216)  评论(0编辑  收藏  举报