洛谷P3809 后缀数组模板

把题读清楚,题中的输入是包括数字、大写字母和小写字母的。
初始化排名的时候可以把字符的ascii值作为排位,因为排名是可以并列的。但是最后的后缀排名是不可能并列的,因为每一个后缀的长度不一样。
基数排序的时候,注意处理并列的情况。下面的代码是复旦大学的程序设计里面的代码,写的挺清晰的,想看的可以直接粘走。

#include <bits/stdc++.h>
using namespace std;

const int maxn=1e6+10;

struct Node {
    int next,now;
}d[maxn];

int pos[maxn],c[maxn],SA[maxn],Rank[maxn],val[maxn][2],n;
char s[maxn];

void add_value(int u,int v,int i)
{
    d[i].next=c[u];
    c[u]=i;
    d[i].now=v;
}

void radix_sort(int l,int r)
{
    for (int k=1;k>=0;k--) {
        memset(c,0,sizeof(c));
        for (int i=r;i>=l;i--) {
            add_value(val[pos[i]][k],pos[i],i);
        }
        int t=0;
        for (int i=0;i<maxn;i++) {
            for (int j=c[i];j;j=d[j].next) {
                pos[++t]=d[j].now;
            }
        }
    }
    int t=0;
    for (int i=1;i<=n;i++) {
        if (val[pos[i]][0]!=val[pos[i-1]][0]||val[pos[i]][1]!=val[pos[i-1]][1]) ++t;
        Rank[pos[i]]=t;
    }

}

void get_suffix_array()
{
    int t=1;
    while (t/2<=n) {
        for (int i=1;i<=n;i++) {
            val[i][0]=Rank[i];
            val[i][1]=(i+t/2<=n)?Rank[i+t/2]:0;
            pos[i]=i;
        }
        
        // for (int i=1;i<=n;i++) {
        //     printf("val: %d %d
",val[i][0],val[i][1]);
        // }

        radix_sort(1,n);
        t*=2;

        // for (int i=1;i<=n;i++) {
        //     printf("%d ",Rank[i]);
        // }
        // puts("");
        // printf("%d%t",t);

    }
    for (int i=1;i<=n;i++) {
        SA[Rank[i]]=i;
    }
}

int main()
{
    freopen("in.txt","r",stdin);
    scanf("%s",s+1);
    n=strlen(s+1);
    for (int i=1;i<n+1;i++) {
        Rank[i]=(int)s[i];
        // printf("%d ",Rank[i]);
    }
    get_suffix_array();
    for (int i=1;i<=n;i++) {
        printf("%d",SA[i]);
        if (i<n) putchar(' ');
    }
    return 0;
}
原文地址:https://www.cnblogs.com/xyqxyq/p/12328858.html