zoukankan      html  css  js  c++  java
  • 2020牛客暑期多校训练营(第一场)B-Suffix Array 后缀数组结论

    题目传送门:B-Suffix Array

    题意:一个字符串S的B数组定义为,如果存在Sj==Si,j<i,则B[i]=i-j,否则B[i]=0。给定字符串S,给出它所有后缀按它们的B数组排序后的顺序。

    我不会。种下一片草地艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹艹

    根据题解就是,对于这种二元串(只含有两种元素),存在一个C数组,C数组的定义是如果存在Sj==Si,j>i,则C[i]=i-j,否则C[i]=lens(S的长度)。

    对于B数组来说,S后缀的B数组不一定是它的B数组的后缀,但对C数组,S后缀的C数组一定是它的C数组的后缀。

    而按照B数组排序,和按照C数组排序,得到的顺序是相反的。大佬的证明

    所以我们只需要把S的C数组求出后缀数组的sa,再倒序输出就好。

    小细节处理,在原本B中,像0,00,000,中肯定是越短的越前面,而C中n,nn,nnn我们则需要让越短的在越后面,做法就是在末尾添加n+1即可。

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e5+11;
    char s[N]; 
    int a[N];
    int sa[N],ra[N];
    int cntr[N],tsa[N];
    void sasort(int n,int m){
        for(int i=0;i<=m;i++) cntr[i]=0;
        for(int i=1;i<=n;i++) cntr[ra[i]]++;
        for(int i=1;i<=m;i++) cntr[i]+=cntr[i-1];
        for(int i=n;i>=1;i--) sa[cntr[ra[tsa[i]]]--]=tsa[i];
    }
    void getsa(int n){
        int m=n;
        for(int i=1;i<=n;i++) ra[i]=a[i],tsa[i]=i;
        sasort(n,m);
        for(int l=1;l<=n;l<<=1){
            int num=0;
            for(int i=n-l+1;i<=n;i++) tsa[++num]=i;
            for(int i=1;i<=n;i++) if(sa[i]>l) tsa[++num]=sa[i]-l; 
            sasort(n,m);
            memcpy(tsa,ra,(n+1)*sizeof(int));
            ra[sa[1]]=1;
            for(int i=2;i<=n;i++){
                ra[sa[i]]=ra[sa[i-1]];
                if(tsa[sa[i]]!=tsa[sa[i-1]]||tsa[sa[i]+l]!=tsa[sa[i-1]+l]) ra[sa[i]]++;
            }
            m=ra[sa[n]];
            if(m>=n) break;
        }
    }
    int main(){
        int n;
        while(~scanf("%d",&n)){
            scanf("%s",s+1);
            int ba=0,bb=0;
            for(int i=n;i>=1;i--){
                if(s[i]=='a'){
                    if(!ba) a[i]=n;
                    else a[i]=ba-i;
                    ba=i;
                }else{
                    if(!bb) a[i]=n;
                    else a[i]=bb-i;
                    bb=i;
                }
            }
            ++n;a[n]=n;
            getsa(n);
            for(int i=n-1;i>=1;i--) printf("%d%c",sa[i]," 
    "[i==1]);
        }
        return 0;
    } 
    证明啥不会,题解第一名
  • 相关阅读:
    JavaScript 类私有方法的实现
    sublime小程序插件
    显示引擎innodb状态详解
    JAVA学习资料大全
    mongo-aggregate命令详解
    PHP error_reporting
    mongo基本命令
    php56升级后php7 mcrypt_encrypt 报错
    docker 基础命令
    敏捷建模:增强沟通和理解
  • 原文地址:https://www.cnblogs.com/LMCC1108/p/13330533.html
Copyright © 2011-2022 走看看