1. 程式人生 > >字尾陣列的基數排序實現

字尾陣列的基數排序實現

基數排序(不懂基數排序的看這裡-->基數排序

基數排序的時間複雜度是O(n),總的時間複雜度是O(n*logn)

C++程式碼實現:

#include <bits/stdc++.h>
using namespace std;
#define infy 0x3f3f3f3f
#define lowbit(x) (x&(-x))
#define e exp(1)
#define pi acos(-1)
typedef long long int ll;
const int maxn=1e6+9;
string str;
int n;
int sa[maxn],c[maxn],tp[maxn],Rank[maxn];
void get_sa(int m)
{
    for(int i=1;i<=m;i++)
        c[i]=0;
    for(int i=1;i<=n;i++)
        c[Rank[i]=str[i]]++;
    for(int i=2;i<=m;i++)
        c[i]+=c[i-1];
    for(int i=n;i>=1;i--)
        sa[c[Rank[i]]--]=i;
    for(int k=1;k<=n;k<<=1)
    {
        int p=1;
        //排序第二關鍵字
        for(int i=n-k+1;i<=n;i++)
            tp[p++]=i;
        for(int i=1;i<=n;i++)
            if(sa[i]>k)
            tp[p++]=sa[i]-k;
        //排序第一關鍵字
        for(int i=1;i<=m;i++)
            c[i]=0;
        for(int i=1;i<=n;i++)
            c[Rank[i]]++;
        for(int i=2;i<=m;i++)
            c[i]+=c[i-1];
        for(int i=n;i>=1;i--)
            sa[c[Rank[tp[i]]]--]=tp[i];
        tp[sa[1]]=1;
        p=1;
        for(int i=2;i<=n;i++)
        {
            int fg=1;
            if(Rank[sa[i]]==Rank[sa[i-1]])
            {
                int xx=sa[i]+k>n?-1:Rank[sa[i]+k];
                int yy=sa[i-1]+k>n?-1:Rank[sa[i-1]+k];
                if(xx==yy)
                    fg=0;
            }
            p+=fg;
            tp[sa[i]]=p;
        }
        swap(Rank,tp);
        if(p>=n)
            break;
        m=p;
    }
}
int main()
{
    cin.sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>str;
    n=str.size();
    str=" "+str;
    get_sa('z'+1);
    for(int i=1;i<n;i++)
        cout<<sa[i]<<" ";
    cout<<sa[n]<<endl;
	return 0;
}