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; }