luogu P3809 【模板】后缀排序

二次联通门 : luogu P3809 【模板】后缀排序

LibreOJ : LibreOJ  #111. 后缀排序

/*
    luogu P3809 【模板】后缀排序
    
    后缀数组
    sa表示 排名为i的是第几个后缀 
    
    求出sa数组后输出即可 
*/ 
#include <cstdio>
#include <cstring>
#define Max 1000008

void read (int &now)
{
    register char word = getchar ();
    for (now = 0; word < '0' || word > '9'; word = getchar ());
    for (; word >= '0' && word <= '9'; now = now * 10 + word - '0');
}

inline void Swap (int *&a, int *&b)
{
    int *now = a;
    a = b; 
    b = now;
}
 
int sa[Max], rank[Max];
int height[Max];

char line[Max];
int str_1[Max], str_2[Max];

int N, M;


void Get_Suffix ()
{
    register int i;
    static int c[Max], *x = str_1, *y = str_2;

    for (i = 0; i < M; c[i ++] = 0);
    for (i = 0; i < N; c[x[i] = line[i]] ++, i ++);
    for (i = 1; i < M; c[i] += c[i - 1], i ++);
    for (i = N - 1; i >= 0; sa[-- c[x[i]]] = i --);
    register int pos;
    pos = 1;
    for (int j = 1; pos < N; j <<= 1, M = pos)
    {
        pos = 0;
        for (i = N - j; i < N; y[pos ++] = i ++);

        for (i = 0; i < N; i ++)
            if (sa[i] >= j)
                y[pos ++] = sa[i] - j;

        for (i = 0; i < M; c[i ++] = 0);
        for (i = 0; i < N; c[x[y[i]]] ++, i ++);
        for (i = 0; i < M; c[i] += c[i - 1], i ++);
        for (i = N - 1; i >= 0; sa[-- c[x[y[i]]]] = y[i --]);
        Swap (x, y);
        pos = 1;
        x[sa[0]] = 0;
        for (i = 1; i < N; i ++)
            x[sa[i]] = y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + j] == y[sa[i] + j] ? pos - 1 : pos ++;
    }
}

int main (int argc, char *argv[])
{
    scanf ("%s", line);
    N = strlen (line);
    M = 200;
    
    Get_Suffix ();
    
    for (int i = 0; i < N; i ++)
        printf ("%d ", sa[i] + 1);

    return 0;
}
原文地址:https://www.cnblogs.com/ZlycerQan/p/7300624.html