• 不同子串


      题目描述:给定一个有小写英文字母构成的字符串T,求其不同子串个数

      数据范围及限制:一个串,长度不超过100000

      输入样例1:

        ababa

      输出样例1:

        9

      输入样例2:

        ebvylfeicorjhpovljmgqawckptcqfuynhvnqwokvowxjgvjhztxmgzwkgvuvhsilrslnzcvmconbabwrpfniknqsimyutwstzzc

      输出样例2:

        4968

      输入样例3:

        riokzisztaydqovqjcdnojfykqjfstevddxtxbtwgzlmwqnhijuemkxaaqmjqscdpnzgseezaexluxdmdkoijafpecganbycwsjs

      输出样例3: 

        4999757677

      题解:

        因为每个子串都是某个后缀的前缀,所以想到用后缀数组,首先要知道后缀数组中height[i]的含义,height[i]不仅指排名第i的和排名第i-1的(后缀)的最长相同前缀,还指排名第i的和排名1~i-1的最长相同前缀,可以举几个例子试试。

        知道了这个性质,那么每一个后缀中只能由它得到的前缀的个数就是n-sa[i]-height[i],n-sa[i]得到这个后缀的长度(我是从0开始的),height[i]个前缀在排名1~i-1的后缀中已经得到,所以要减去,不计入答案。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<algorithm>
     6 #include<queue>
     7 #include<vector>
     8 using namespace std;
     9 typedef long long LL;
    10 const LL maxn=200000;
    11 LL r[maxn],sa[maxn],wa[maxn],wb[maxn],wv[maxn],Ws[maxn];
    12 LL cmp(LL *r,LL a,LL b,LL l){
    13     return r[a]==r[b]&&r[a+l]==r[b+l];
    14 }
    15 void da(LL *r,LL *sa,LL n,LL m){
    16     LL i,j,p,*x=wa,*y=wb,*t;
    17     for(i=0;i<m;i++) Ws[i]=0;
    18     for(i=0;i<n;i++) Ws[x[i]=r[i]]++;
    19     for(i=1;i<m;i++) Ws[i]+=Ws[i-1];
    20     for(i=n-1;i>=0;i--) sa[--Ws[x[i]]]=i; 
    21     
    22     for(j=1,p=1;p<n;j*=2,m=p){
    23         for(p=0,i=n-j;i<n;i++) y[p++]=i;
    24         for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
    25         
    26         for(i=0;i<n;i++) wv[i]=x[y[i]];        
    27         for(i=0;i<m;i++) Ws[i]=0;
    28         for(i=0;i<n;i++) Ws[wv[i]]++;
    29         for(i=0;i<m;i++) Ws[i]+=Ws[i-1];
    30         for(i=n-1;i>=0;i--) sa[--Ws[wv[i]]]=y[i];
    31         
    32         for(t=x,x=y,y=t,x[sa[0]]=0,p=1,i=1;i<n;i++)
    33             x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
    34     }
    35 }
    36 LL rank[maxn],height[maxn];
    37 void calheight(LL *r,LL *sa,LL n){
    38     LL i,j,k=0;
    39     for(i=0;i<n;i++) rank[sa[i]]=i;
    40     for(i=0;i<n;height[rank[i++]]=k)
    41         for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++);
    42     return ;
    43 }
    44 char s[maxn];
    45 LL num[maxn],len,ans;
    46 int main(){
    47     freopen("distinct.in","r",stdin);
    48     freopen("distinct.out","w",stdout);
    49     scanf("%s",s); len=strlen(s);
    50     for(LL i=0;i<len;i++) num[i]=s[i]-'a'+2;
    51     da(num,sa,len,30);
    52     calheight(num,sa,len); height[0]=0;
    53     for(LL i=0;i<len;i++){
    54         LL k=len-sa[i];
    55         ans+=k-height[i];
    56     }
    57     printf("%lld",ans);
    58     return 0;
    59 }
  • 相关阅读:
    Python subprocess- call、check_call、check_output
    Java Annotation认知(包括框架图、详细介绍、示例说明) (转)
    NVME SSD vs SATA SSD(转)
    scala中“_”的用法
    maven scope 'provided' 和 ‘compile’的区别
    scala tuple中的syntactic sugar
    Scala中的"null" 和“_”来初始化对象
    scala可变长度参数(转)
    Java中的Builder模式
    Scala中“=>”用法及含义
  • 原文地址:https://www.cnblogs.com/CXCXCXC/p/5176984.html
Copyright © 2020-2023  润新知