zoukankan      html  css  js  c++  java
  • B-Suffix Array

    A. B-Suffix Array

    参考:2020年牛客多校A题

    将字符串化为B数组之后,会发现,它其实是由两部分组成的。例如aaaabaaab的B数组为011102114,那么我们可以将B拆成两半,前面一部分是01110,后面一部分是2114。我们会发现,所有长度的B数组前面部分的格式都是一样的,而后面一部分都是(B(t_1..t_n))的子串。

    所以我们可以先对前面一部分对长度进行排序,再用后缀数组对后面那部分进行排序。

    但是我们会发现,前面这部分排序的过程中,0111和0110的长度是一样的,要把他区别开来,所以就让0111的长度变为4.5,这样既满足了比0110大,又满足了比01110小。

    // Created by CAD on 2020/7/14.
    #include <bits/stdc++.h>
    
    #define fi first
    #define se second
    #define pfii pair<pair<float,int>,int>
    using namespace std;
    
    vector<pfii> v;
    const int maxn=1e5+5;
    int cnt[maxn];
    
    void radix(int *str,int *a,int *b,int n,int m){
        for(int i=0;i<=m;++i) cnt[i]=0;
        for(int i=0;i<n;++i) ++cnt[str[a[i]]];
        for(int i=1;i<=m;++i) cnt[i]+=cnt[i-1];
        for(int i=n-1;i>=0;--i) b[--cnt[str[a[i]]]]=a[i];
    }
    int rk[maxn],a[maxn],b[maxn];
    void suffix_array(int *str,int *sa,int n,int m){
        for(int i=0;i<n;++i) rk[i]=i;
        radix(str,rk,sa,n,m);
    
        rk[sa[0]]=0;
        for(int i=1;i<n;++i) rk[sa[i]]=rk[sa[i-1]]+(str[sa[i]]!=str[sa[i-1]]);
        for(int i=0;1<<i <n;++i){
            for(int j=0;j<n;++j){
                a[j]=rk[j]+1;
                b[j]=j+(1<<i)>=n?0:rk[j+(1<<i)]+1;
                sa[j]=j;
            }
            radix(b,sa,rk,n,n);
            radix(a,rk,sa,n,n);
            rk[sa[0]]=0;
            for(int j=1;j<n;++j)
                rk[sa[j]]=rk[sa[j-1]]+(a[sa[j-1]]!=a[sa[j]]||b[sa[j-1]]!=b[sa[j]]);
        }
    }
    int t[maxn],sa[maxn];
    int main() {
        int n;
        while(cin>>n){
            string s;cin>>s;
            v.clear();
            int aa=0,bb=0;
    
            for(int i=0;i<n;++i){
                while(aa<n-1&&(aa < i || s[aa] != 'a')) aa++;
                while(bb<n-1&&(bb < i || s[bb] != 'b')) bb++;
                v.push_back({{abs(bb - aa) + 1+((s[aa]!='a'||s[bb]!='b')?0.5:0), n - i - (abs(bb - aa) + 1)}, i+1});
            }
            aa=-1, bb=-1;
            int m=0;
            for(int i=0;i<n;++i)
                if(s[i]=='a') t[i]=(~aa ? (i - aa) : 0), aa=i,m=max(m,t[i]);
                else t[i]=(~bb ? (i - bb) : 0), bb=i,m=max(m,t[i]);
            suffix_array(t,sa,n,m);
            rk[n]=-1;
            for(auto &i:v)
                i.fi.se=rk[n-i.fi.se]+1;
            sort(v.begin(),v.end());
            for(auto i:v)
                cout<<i.se<<" ";
            cout<<endl;
        }
        return 0;
    }
    
    CAD加油!欢迎跟我一起讨论学习算法,QQ:1401650042
  • 相关阅读:
    基于 .NET Core 的简单文件服务器
    重启博客园,走出第一步
    layui扩展组件zTreeSelectM,下拉树多选
    skyline加载arcgis发布的wms服务
    HTML&CSS:构建网站不能不说的那些事儿
    VueCLi3 配置less变量
    Bootstrap4 本地编译运行
    冒泡排序和选择排序
    Router
    ToDoList
  • 原文地址:https://www.cnblogs.com/CADCADCAD/p/13303700.html
Copyright © 2011-2022 走看看