[后缀数组]luogu 3809 后缀排序

https://www.luogu.org/problemnew/show/P3809

分析

SA模板(找个时间把SA学习笔记写了)

 

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N=1e6+10;
int n,m;
int c[N],x[N],y[N],sa[N],rk[N],height[N];
char s[N];

void SA() {
    memset(c,0,sizeof c);
    for (int i=1;i<=n;i++) c[x[i]=s[i]]++;
    for (int i=1;i<=m;i++) c[i]+=c[i-1];
    for (int i=n;i;i--) sa[c[x[i]]--]=i;
    for (int k=1;k<=n;k<<=1) {
        memset(c,0,sizeof c);int cnt=0;
        for (int i=n-k+1;i<=n;i++) y[++cnt]=i;
        for (int i=1;i<=n;i++) if (sa[i]>k) y[++cnt]=sa[i]-k;
        for (int i=1;i<=n;i++) c[x[i]]++;
        for (int i=1;i<=m;i++) c[i]+=c[i-1];
        for (int i=n;i;i--) sa[c[x[y[i]]]--]=y[i],y[i]=0;
        swap(x,y);cnt=0;
        x[sa[1]]=++cnt;
        for (int i=2;i<=n;i++)
        x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k])?cnt:++cnt;
        m=cnt;
    }
}

int main() {
    scanf("%s",s+1);
    n=strlen(s+1);m='z';
    SA();
    for (int i=1;i<=n;i++) printf("%d ",sa[i]);
}
View Code

 

posted @ 2019-07-10 21:42  Vagari  阅读(129)  评论(0编辑  收藏  举报