P3809 【模板】后缀排序

P3809 【模板】后缀排序

从这学的

后缀数组sa[i]就表示排名为i的后缀的起始位置

x[i]是第i个元素的第一关键字

y[i]表示第二关键字排名为i的数,在第一关键字中的位置

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define N 1000005
#define rint register int
int n,m,c[N],sa[N],x[N],y[N]; char s[N];
void get_sa(){
    for(rint i=1;i<=n;++i) ++c[x[i]=s[i]];
    for(rint i=1;i<=m;++i) c[i]+=c[i-1];
    for(rint i=n;i>=1;--i) sa[c[x[i]]--]=i;
    for(rint k=1;k<=n;k<<=1){
        rint u=0;
        for(rint i=n-k+1;i<=n;++i) y[++u]=i;//逆序也没关系,因为都是没有
        for(rint i=1;i<=n;++i) if(sa[i]>k) y[++u]=sa[i]-k;
        for(rint i=1;i<=m;++i) c[i]=0;
        for(rint i=1;i<=n;++i) ++c[x[i]];
        for(rint i=1;i<=m;++i) c[i]+=c[i-1];
        for(rint i=n;i>=1;--i) sa[c[x[y[i]]]--]=y[i],y[i]=0;//按第二关键字排序
        swap(x,y); x[sa[1]]=1; u=1;
        for(rint i=2;i<=n;++i)
            x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k])?u:++u;
        if(u==n){break;} m=u;
    }
}
int main(){
    scanf("%s",s+1); n=strlen(s+1),m=125;
    get_sa();
    for(rint i=1;i<=n;++i) printf("%d ",sa[i]);
    return 0;
}

sa求最长公共前缀

void get_height() //求最长公共前缀
{
    for(rint i=1;i<=n;i++) rk[sa[i]]=i;
    rint k=0;
    for(rint i=1;i<=n;i++)
    {
        if(rk[i]==1) continue;
        if(k) --k;
        rint j=sa[rk[i]-1];
        while(i+k<=n&&j+k<=n&&s[i+k]==s[j+k]) ++k;
        height[rk[i]]=k;
    }
}

 

posted @ 2019-04-01 22:01  kafuuchino  阅读(211)  评论(0编辑  收藏  举报