zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    如何改计算机用户名
    解决windows弹出'你可能是盗版软件的受害者...'及去除自动更新图标
    关于复制文件出现“Thumbs:访问被拒绝......”的解决办法和相关知识
    <百度分享平台>透明FLASH模块的方法
    绝对性解决打开我的电脑打开文件夹在新窗口中打开问题
    Git忽略规则(.gitignore配置)不生效原因和解决
    汇编学习笔记18
    汇编学习笔记21
    汇编学习笔记16
    汇编学习笔记22
  • 原文地址:https://www.cnblogs.com/wfj2048/p/7633054.html
Copyright © 2011-2022 走看看