zoukankan      html  css  js  c++  java
  • bzoj 4566 [Haoi2016]找相同字符SA

    4566: [Haoi2016]找相同字符

    Time Limit: 20 Sec  Memory Limit: 256 MB
    Submit: 128  Solved: 75
    [Submit][Status][Discuss]

    Description

    给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数。两个方案不同当且仅当这两
    个子串中有一个位置不同。

    Input

    两行,两个字符串s1,s2,长度分别为n1,n2。1 <=n1, n2<= 200000,字符串中只有小写字母

    Output

    输出一个整数表示答案

    Sample Input

    aabb
    bbaa

    Sample Output

    10
     
    从大到小扫描height数组,合并相邻后缀,因为从大到小枚举,所以当前块中的贡献就是第一个串的后缀数*第二个串的后缀数*当前枚举的height。用并查集维护即可。
    算了,学了后缀自动机在来切吧。
     1 #include<cstring>
     2 #include<cmath>
     3 #include<iostream>
     4 #include<algorithm>
     5 #include<cstdio>
     6 
     7 #define ll long long
     8 #define N 200007
     9 using namespace std;
    10 
    11 int n,fa[N];
    12 int cnta[N<<1],cntb[N<<1],sa[N<<1],rk[N<<2],a[N<<1],b[N<<1],tsa[N<<1],height[N<<1],g[N<<1],f[N<<1],A[N<<1],B[N<<1];
    13 char s1[N],s2[N],s[N*2];
    14 
    15 void Get_SA()
    16 {
    17     for (int i=0;i<=256;i++)cnta[i]=0;
    18     for (int i=1;i<=n;i++)cnta[(int)s[i]]++;
    19     for (int i=1;i<=256;i++)cnta[i]+=cnta[i-1];
    20     for (int i=n;i>=1;i--)sa[cnta[(int)s[i]]--]=i;
    21     rk[sa[1]]=1;
    22     for (int i=2;i<=n;i++)rk[sa[i]]=rk[sa[i-1]]+(s[sa[i]]!=s[sa[i-1]]);
    23     for (int i=1;rk[sa[n]]!=n;i<<=1)
    24     {
    25         for (int j=1;j<=n;j++)a[j]=rk[j],b[j]=rk[j+i];
    26         for (int j=0;j<=n;j++)cnta[j]=cntb[j]=0;
    27         for (int j=1;j<=n;j++)cnta[a[j]]++,cntb[b[j]]++;
    28         for (int j=1;j<=n;j++)cnta[j]+=cnta[j-1],cntb[j]+=cntb[j-1];
    29         for (int j=n;j>=1;j--)tsa[cntb[b[j]]--]=j;
    30         for (int j=n;j>=1;j--)sa[cnta[a[tsa[j]]]--]=tsa[j];
    31         rk[sa[1]]=1;
    32         for (int j=2;j<=n;j++)
    33             rk[sa[j]]=rk[sa[j-1]]+(a[sa[j]]!=a[sa[j-1]]||b[sa[j]]!=b[sa[j-1]]);
    34     }
    35 }
    36 void Get_Height()
    37 {
    38     int len=0;
    39     for (int i=1;i<=n;i++)
    40     {
    41         if (len)len--;
    42         while(s[i+len]==s[sa[rk[i]-1]+len])len++;
    43         height[rk[i]]=len;
    44     }
    45 }
    46 bool cmp(int x,int y){return height[x]>height[y];}
    47 int find(int x)
    48 {
    49     if (f[x]!=x)f[x]=find(f[x]);
    50     return f[x];
    51 }
    52 int main()
    53 {
    54     scanf("%s",s1+1);int len1=strlen(s1+1);
    55     scanf("%s",s2+1);int len2=strlen(s2+1);
    56     n=len1+len2+1;
    57     for (int i=1;i<=n;i++)
    58         if (i==len1+1){s[i]=(char)27;continue;}
    59         else s[i]=(i<=len1)?s1[i]-'a'+1:s2[i-len1-1]-'a'+1;
    60     Get_SA();
    61     Get_Height();
    62     /*for (int i=1;i<=n;i++)
    63         cout<<height[i]<<" ";
    64     cout<<endl;*/
    65     for (int i=1;i<=n;i++)
    66     {
    67         g[i]=i+1;
    68         f[i]=i;
    69         if (sa[i]<=len1)A[i]=1;
    70         if (sa[i]>len1+1)B[i]=1;
    71     }
    72     sort(g+1,g+n,cmp);
    73     ll ans=0;
    74     for (int i=1;i<=n-1;i++)
    75     {
    76         int x=find(g[i]),y=find(g[i]-1);
    77         ans+=((ll)A[y]*B[x]+(ll)A[x]*B[y])*height[g[i]];
    78         A[y]+=A[x],B[y]+=B[x];
    79         f[x]=y;
    80     }
    81     printf("%lld",ans);
    82 }
  • 相关阅读:
    Mac 国内安装homebrew办法
    字符串方法及注释
    文件的操作
    集合
    Mac下CVS文件编码转换
    字符串格式化
    postman常用断言的一些内置方法
    get与post区别
    pygame知识点(持续更新)
    记录第一次使用
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8277574.html
Copyright © 2011-2022 走看看