后缀排序

luogu P3809 为例

#include <cstdio>
#include <cstring>
#define R register
const int MaxN = 1000010;
int SA[MaxN], Rank[MaxN], Height[MaxN], x[MaxN], sum[MaxN], y[MaxN];
char s[MaxN];
bool cmp(R int i, R int j, R int k){ return x[i] == x[j] && x[i + k] == x[j + k]; } 
int main()
{
    scanf("%s", s + 1);
    R int n = strlen(s + 1), m = 128;
    for(R int i = 1; i <= n; i++) sum[x[i] = s[i]]++;
    for(R int i = 1; i <= m; i++) sum[i] += sum[i - 1];
    for(R int i = n; i; i--) SA[sum[x[i]]--] = i;
    for(R int i = 1; i < n; i <<= 1)
    {
        R int pos = 0; //此时的y是用于计算SA数组的
        for(R int j = n - i + 1; j <= n; j++) y[++pos] = j; //将长度小于2^i的后缀的第二关键字为0,肯定排在前头,而且按照从前往后的顺序
        for(R int j = 1; j <= n; j++) if(SA[j] > i) y[++pos] = SA[j] - i; //这一步其实把第二关键字非0的都加入了,SA[j]<=i的数都排在前i个,一定不会作为其他数的第二关键字
        for(R int j = 1; j <= m; j++) sum[j] = 0;
        for(R int j = 1; j <= n; j++) sum[x[j]]++;
        for(R int j = 1; j <= m; j++) sum[j] += sum[j - 1];
        for(R int j = n; j; j--) SA[sum[x[y[j]]]--] = y[j];  //根据第二关键字给出的顺序,进行第一关键字的排序 
        y[SA[1]] = 1; //此时的y是用于计算x数组的,与前面的用途没有任何关系
        for(R int j = 2; j <= n; j++) y[SA[j]] = y[SA[j - 1]] + !cmp(SA[j], SA[j - 1], i);
        for(R int j = 1; j <= n; x[j] = y[j], j++);
        m = x[SA[n]];
        if(m == n) break;
    }
    for(R int i = 1; i <= n; i++) printf("%d ", SA[i]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值