zoukankan      html  css  js  c++  java
  • SA-题目

    SA的题目

      差异https://lydsy.com/JudgeOnline/problem.php?id=3238

      题意概述:给定一个长度为 $n$ 的字符串 $S$,令 $T_ i$ 表示它从第 $i$ 个字符开始的后缀。$2<=N<=50000$。求$$sum_{1<=i<j<=n}len(T_i)+len(T_j)-2 imes lcp(T_i,T_j)$$

    ​  通过观察可以发现,每个后缀的长度被计算的次数是 $n-1$ ,而所有后缀长度的和是一个等差数列,$frac{n imes(n+1)}{2}$,所以式子的前半部分就是 $frac{(n^3-n)}{2}$ 。

    ​  现在来求后半部分,等价于所有后缀对的 $lcp$ 之和再乘二,看到后缀,我就想到 $SA$,看到 $lcp$ ,我就想到求 $height$ 数组,求出 $height$ 数组,原问题就转化为整个序列中(每个区间的最小值)之和。

    ​  这个问题可以用单调栈扫两遍,找到每个点可以作为最小值的左右端点,并注意一下边界情况,有相同最小值的时候不要算重复就可以通过了。

    ​  对于这种问题还有另一个很不错的方法:烜式合并;这是烜神仙的 $blog$ :https://www.cnblogs.com/asuldb/p/10205640.html

      
     1 # include <cstdio>
     2 # include <iostream>
     3 # include <cstring>
     4 # include <string>
     5 # define R register int
     6 # define ll long long
     7  8 using namespace std;
     9 10 const int maxn=500005;
    11 char c[maxn];
    12 int n,sa[maxn],ht[maxn],ta[maxn],tb[maxn],A[maxn],B[maxn],rk[maxn],m,l[maxn],r[maxn],Tp,k[maxn],v[maxn];
    13 ll ans,anss;
    14 15 inline void build_SA()
    16 {
    17     for (R i=1;i<=n;++i) ta[ c[i] ]++;
    18     for (R i=1;i<=200;++i) ta[i]+=ta[i-1];
    19     for (R i=n;i>=1;--i) sa[ ta[ c[i] ]-- ]=i;
    20     rk[ sa[1] ]=1;
    21     for (R i=2;i<=n;++i) rk[ sa[i] ]=(c[ sa[i] ]==c[ sa[i-1] ])?rk[ sa[i-1] ]:rk[ sa[i-1] ]+1;
    22     for (R l=1;rk[ sa[n] ]<n;l<<=1)
    23     {
    24         for (R i=1;i<=n;++i) ta[i]=tb[i]=0;
    25         for (R i=1;i<=n;++i)
    26         {
    27             ta[ A[i]=rk[i] ]++;
    28             tb[ B[i]=(i+l<=n)?rk[i+l]:0 ]++;
    29         }
    30         for (R i=1;i<=n;++i) ta[i]+=ta[i-1],tb[i]+=tb[i-1];
    31         for (R i=n;i>=1;--i) rk[ tb[ B[i] ]-- ]=i;
    32         for (R i=n;i>=1;--i) sa[ ta[ A[ rk[i] ] ]-- ]=rk[i];
    33         rk[ sa[1] ]=1;
    34         for (R i=2;i<=n;++i)
    35         {
    36             rk[ sa[i] ]=rk[ sa[i-1] ];
    37             if(A[ sa[i] ]!=A[ sa[i-1] ]||B[ sa[i] ]!=B[ sa[i-1] ]) rk[ sa[i] ]++;
    38         }
    39     }
    40     int j=0;
    41     for (R i=1;i<=n;++i)
    42     {
    43         if(j) j--;
    44         while (c[ i+j ]==c[ sa[ rk[i]-1 ]+j ]) j++; 
    45         ht[ rk[i] ]=j;
    46     }
    47 }
    48 49 int main()
    50 {
    51     scanf("%s",c+1);
    52     n=strlen(c+1);
    53     ans=1LL*n*(n+1)/2*(n-1);
    54     build_SA();
    55     for (R i=1;i<=n;++i)
    56     {
    57         while(Tp&&ht[i]<v[Tp]) r[ k[Tp] ]=i-k[Tp],Tp--;
    58         k[++Tp]=i,v[Tp]=ht[i];
    59     }
    60     for (R i=1;i<=Tp;++i) r[ k[i] ]=n-k[i]+1;
    61     Tp=0;
    62     for (R i=n;i>=1;--i)
    63     {
    64     while(Tp&&ht[i]<=v[Tp]) l[ k[Tp] ]=k[Tp]-i,Tp--;
    65     k[++Tp]=i,v[Tp]=ht[i];
    66     }
    67 for (R i=1;i<=Tp;++i) l[ k[i] ]=k[i]-1;
    68 for (R i=1;i<=n;++i) anss+=1LL*l[i]*r[i]*ht[i];
    69     printf("%lld",ans-anss*2);
    70     return 0;
    71 }
    差异
  • 相关阅读:
    DBA操作常用命令
    DBA常用SQL
    安装下rlwrap
    destoon复制新模块的方法
    生成二维码
    布隆过滤
    Golang中的三个点
    Golang: 数组和切片
    Fabric的权限管理:Attribute-Based Access Control
    Node.js web发布到AWS ubuntu 之后,关闭Putty,Node 项目也随之关闭的解决办法
  • 原文地址:https://www.cnblogs.com/shzr/p/10296957.html
Copyright © 2011-2022 走看看