洛谷P3809 【模板】后缀排序

P3809 【模板】后缀排序

题目链接

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

题目背景

这是一道模板题。

题目描述

读入一个长度为 n n n 的由大小写英文字母或数字组成的字符串,请把这个字符串的所有非空后缀按字典序从小到大排序,然后按顺序输出后缀的第一个字符在原串中的位置。位置编号为 1 1 1 到 n n n。

输入输出格式

输入格式:

一行一个长度为 n n n 的仅包含大小写英文字母或数字的字符串。

输出格式:

一行,共n个整数,表示答案。

输入输出样例

输入样例#1:

ababa

输出样例#1:

5 3 1 4 2

Hint

$n le10^6 $

题解

后缀数组模板题,我将其封装了,所以多了个求lcp的功能这题用不到。

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 1000050
template<typename T>void read(T&x)
{
    ll k=0; char c=getchar();
    x=0;
    while(!isdigit(c)&&c!=EOF)k^=c=='-',c=getchar();
    if (c==EOF)exit(0);
    while(isdigit(c))x=x*10+c-'0',c=getchar();
    x=k?-x:x;
}
void read_char(char &c)
{while(!isalpha(c=getchar())&&c!=EOF);}
struct SuffixArray
{
    string s;
    int n,c[N],t1[N],t2[N];
    int kth[N],rk[N],mm[N],he[N][21];
    void BuildKth()
        {
            int *x=t1,*y=t2;
            n=s.size()-1;
            int m=300;
            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>=1;i--)kth[c[x[i]]--]=i;
            for(int k=1;k<n;k<<=1)
            {
                int p=0;
                memset(c,0,sizeof(c));
                
                for(int i=n-k+1;i<=n;i++)y[++p]=i;
                for(int i=1;i<=n;i++)if (kth[i]-k>0)y[++p]=kth[i]-k;
                for(int i=1;i<=n;i++)c[x[y[i]]]++;
                for(int i=1;i<=m;i++)c[i]+=c[i-1];
                for(int i=n;i>=1;i--)kth[c[x[y[i]]]--]=y[i];
                swap(x,y);
                p=0;
                x[kth[1]]=++p;
                for(int i=2;i<=n;i++)
                    x[kth[i]]=y[kth[i]]==y[kth[i-1]]&&y[kth[i]+k]==y[kth[i-1]+k]?p:++p;
                m=p;
                if (m==n)break;
            }
        }
    void GetHeight()
        {
            for(int i=1;i<=n;i++)rk[kth[i]]=i;
            mm[1]=0;
            for(int i=2;i<=n;i++)mm[i]=mm[i>>1]+1;
            int k=0;
            for(int i=1;i<=n;i++)
            {
                if (k)k--;
                int j=kth[rk[i]-1];
                while(s[i+k]==s[j+k]&&i+k<n&&j+k<n)k++;
                he[rk[i]][0]=k;
            }
            for(int i=1;i<=20;i++)
                for(int j=1;j+(1<<i)-1<=n;j++)
                    he[j][i]=min(he[j][i-1],he[j+(1<<(i-1))][i-1]);
                
        }
    int Lcp(int x,int y)
        {
            x=rk[x]+1; y=rk[y];
            if (x>y)swap(x,y);
            int k=mm[y-x+1];
            return min(he[x][k],he[y-(1<<k)+1][k]);
        }
}A;
int main()
{
#ifndef ONLINE_JUDGE
    freopen("aa.in","r",stdin);
#endif
    ios::sync_with_stdio(false);
    cin>>A.s; A.s='!'+A.s;
    A.BuildKth();
    for(int i=1;i<=A.n;i++)
        printf("%d ",A.kth[i]);
}

原文地址:https://www.cnblogs.com/mmmqqdd/p/10846837.html