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;
    } 
    证明啥不会,题解第一名
  • 相关阅读:
    Balance的数学思想构造辅助函数
    1663. Smallest String With A Given Numeric Value (M)
    1680. Concatenation of Consecutive Binary Numbers (M)
    1631. Path With Minimum Effort (M)
    1437. Check If All 1's Are at Least Length K Places Away (E)
    1329. Sort the Matrix Diagonally (M)
    1657. Determine if Two Strings Are Close (M)
    1673. Find the Most Competitive Subsequence (M)
    1641. Count Sorted Vowel Strings (M)
    1679. Max Number of K-Sum Pairs (M)
  • 原文地址:https://www.cnblogs.com/LMCC1108/p/13330533.html
Copyright © 2011-2022 走看看