字尾陣列的快速排序實現
阿新 • • 發佈:2018-12-11
快速排序
這種排序方法更容易理解,直接寫一個二元組的比較函式,用sort排序就可以了,每次排序時間複雜度O(n*logn),總的時間複雜度是,一般這個複雜度是可以接受的
題目:
C++程式碼實現:
#include <bits/stdc++.h> using namespace std; #define maxn 1000009 typedef long long int ll; string str;//給定的字串 //string Suffix[maxn];//儲存字串字尾,在不需要輸出字尾的情況下最好不加這個陣列,加上可能會爆記憶體 int n;//字串的大小 int Sa[maxn];//所求的字尾陣列 int Rank[maxn];//表示字尾排第幾的陣列 int tp[maxn];//臨時儲存Rank的值 int k=0; /*void get_Suffix()//得到字串的字尾 { Suffix[n]=str[n]; for(int i=n-1;i>=1;i--) Suffix[i]=str[i]+Suffix[i+1]; }*/ bool comp(int x,int y)// { if(Rank[x]!=Rank[y])//先比較第一關鍵字 return Rank[x]<Rank[y]; //比較第二關鍵字,如果超出n則補為-1,防止陣列越界 int rx=x+k>n?-1:Rank[x+k]; int ry=y+k>n?-1:Rank[y+k]; return rx<ry; } bool judge(int x,int y)//判斷後綴x,y的二元組是否相等 { if(Rank[x]==Rank[y])//先比較第一關鍵字 { //比較第二關鍵字,如果超出n則補為-1,防止陣列越界 int rx=x+k>n?-1:Rank[x+k]; int ry=y+k>n?-1:Rank[y+k]; if(rx==ry) return 1; return 0; } return 0; } void get_Sa() { memset(Rank,0,sizeof(Rank)); for(int i=1;i<=n;i++)//初始化 { Sa[i]=i; Rank[i]=str[i];//第一次的Rank就是字尾的第一個字元,字元的大小就可代表字尾的Rank } for(k=1;k<=n;k<<=1) { sort(Sa+1,Sa+n+1,comp);//根據二元組排序 int fg=0;//fg表示目前的最大次序號,每次初始為0 for(int i=1;i<=n;i++)//按照Sa從小到大給字尾更新次序 { if(judge(Sa[i],Sa[i-1])==0)//如果與前一個二元組不相同,則產生新的次序號,將fg+1 fg++; tp[Sa[i]]=fg; } for(int i=1;i<=n;i++) Rank[i]=tp[i]; if(fg>=n)//最大次序號大於等於n,說明每個字尾都有一個不同的次序號就結束 break; } return ; } int main() { cin>>str; n=str.size(); str=" "+str;//使字串編號是1到n get_Sa(); for(int i=1;i<n;i++) cout<<Sa[i]<<" "; cout<<Sa[n]<<endl; return 0; }