2020牛客多校第一场A题B-Suffix Array(后缀数组)

题目链接https://ac.nowcoder.com/acm/contest/5666/A

题意:

题解:结论

 

下面举例解释

以abaab为例

C数组为当前后面的字符与当前的字符相同时的最少位置差,注意如果是最后的a,b的话它后面无a,b那么结果是无穷大,我这边就让他等于n了,最后一位让它加一位为n+1

C{231556},C的后缀为

231556,32556,1556,556,56,6

后缀sa数组为{312456}  反过来{54213} 就是答案

再来一个例子

ababa

C{222556},C的后缀为

222556,22556,2556,556,56,6

后缀sa数组为{123456}  反过来{54321} 就是答案

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int N = 1e5+7;
int n,c[N],sa[N],tmp[N],ran[N],k;
char s[N];

bool cmp(int i,int j){
    if(ran[i] != ran[j]) return ran[i] < ran[j];
    int ri = i+k<=n+1?ran[i+k]:-1;
    int rj = j+k<=n+1?ran[j+k]:-1;
    return ri < rj;
}

void get_sa(){
    for(int i=0;i<=n+1;i++){
        sa[i] = i;
        ran[i] = i<n+1?c[i]:-1;
    }
    for(k = 1;k <= n+1;k <<= 1){
        sort(sa,sa+n+2,cmp);
        tmp[sa[0]] = 0;
        for(int i=1;i<=n+1;i++)
            tmp[sa[i]] = tmp[sa[i-1]] + (cmp(sa[i-1],sa[i])?1:0);
        for(int i=0;i<=n+1;i++) ran[i] = tmp[i];
    }
}

void get_c(){
    int ta = -1,tb = -1;
    for(int i=n-1;i>=0;i--){
        if(s[i] == 'a'){
            if(ta == -1) c[i] = n,ta = i;
            else c[i] = ta-i,ta = i;
        }else{
            if(tb == -1) c[i] = n,tb = i;
            else c[i] = tb-i,tb = i;
        }
    }
    c[n] = n+1;
}
int main(){
    while(cin>>n>>s){
        get_c();
        get_sa();
        for(int i=n;i>=1;i--) cout<<sa[i]+1<<" ";
        puts("");
    }
    return 0;
}
View Code

 

posted @ 2020-07-31 22:59  杰瑞与汤姆  阅读(155)  评论(0编辑  收藏  举报