日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

初学后缀数组

發布時間:2025/5/22 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 初学后缀数组 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

后綴排序

Description

Tim正在自學《數據結構》,他剛剛學會如何比較兩個字符串大小。書上是這么說的(和Pascal語言中的比較規則相同,學習過Pascal語言的同學可以跳過這段):?
比較兩個不同字符串s1=’p1p2p3…pN’和s2=’q1q2q3…qM’的大小,設N<=M。?
若s1是s2的前綴,則s1<s2。否則設pi<>qi,且i最小;若pi<qi,則s1<s2,否則s1>s2。?
Tim想通過練習熟練運用這個規則,于是打算出許多字符串,并將它們從小到大排序。可是Tim非常懶,隨機寫出 K個很長的字符串實在是太麻煩了。不過聰明的他想到了一個好辦法,他寫了一個很長的字符串,自言自語說,“我只要把這個字符串的所有后綴從小到大排序就可以了”。?

Input

輸入文件suffix.in中僅有一行,且是一個僅包含小寫字母的字符串,長度K不超過10^5。?

Output

有K行,每行一個數字,第i行的數字Pi表示所有后綴中,第i小的是由原字符串第Pi個字符引導的后綴。?

Sample Input

?

mississippi

?

Sample Output

?

11 8 5 2 1 10 9 7 4 6 3

?

Source

Oibh(后綴數組)

?

?

后綴數組:后綴數組SA 是一個一維數組,它保存1..n 的某個排列SA[1],SA[2],……,SA[n],并且保證Suffix(SA[i]) < Suffix(SA[i+1]),1≤i<n。

?

也就是將S 的n 個后綴從小到大進行排序之后把排好序的后綴的開頭位置順次放入SA 中。

?

名次數組:名次數組Rank[i]保存的是Suffix(i)在所有后綴中從小到大排列的“名次”。

?

倍增算法求后綴數組的主要思路是:用倍增的方法對每個字符開始的長度為2k 的子字
符串進行排序,求出排名,即rank 值。k 從0 開始,每次加1,當2k 大于n 以
后,每個字符開始的長度為2k 的子字符串便相當于所有的后綴。并且這些子字
符串都一定已經比較出大小,即rank 值中沒有相同的值,那么此時的rank 值就
是最后的結果。每一次排序都利用上次長度為2k-1 的字符串的rank 值,那么長
度為2k 的字符串就可以用兩個長度為2k-1 的字符串的排名作為關鍵字表示,然
后進行基數排序,便得出了長度為2k 的字符串的rank 值。以字符串“aabaaaab”
為例,整個過程如圖2 所示。其中x、y 是表示長度為2k 的字符串的兩個關鍵字。

?

?

?

code:
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #define maxn 100010 6 using namespace std; 7 char s[maxn]; 8 int n,m,tot,sum[maxn],t1[maxn],t2[maxn],rank[maxn],SA[maxn]; 9 void get_SA(){ 10 int *x=t1,*y=t2; 11 for (int i=1;i<=n;i++) sum[x[i]=s[i]]++; 12 for (int i=1;i<=255;i++) sum[i]+=sum[i-1]; 13 for (int i=1;i<=n;i++) SA[sum[x[i]]--]=i; 14 tot=0; 15 for (int len=1;tot<n;len<<=1,m=tot){ 16 tot=0; 17 for (int i=n-len+1;i<=n;i++) y[++tot]=i; 18 for (int i=1;i<=n;i++) if (SA[i]>len) y[++tot]=SA[i]-len; 19 for (int i=1;i<=m;i++) sum[i]=0; 20 for (int i=1;i<=n;i++) sum[x[y[i]]]++; 21 for (int i=1;i<=m;i++) sum[i]+=sum[i-1]; 22 for (int i=n;i>=1;i--) SA[sum[x[y[i]]]--]=y[i]; 23 swap(x,y); 24 x[SA[1]]=tot=1; 25 for (int i=2;i<=n;i++){ 26 if (y[SA[i]]!=y[SA[i-1]]||y[SA[i]+len]!=y[SA[i-1]+len]) tot++; 27 x[SA[i]]=tot; 28 } 29 } 30 for (int i=1;i<=n;i++) rank[i]=x[i]; 31 } 32 int main(){ 33 scanf("%s",s+1); 34 n=strlen(s+1),m=123; 35 get_SA(); 36 for (int i=1;i<=n;i++) printf("%d\n",SA[i]); 37 return 0; 38 } 39

?

?

轉載于:https://www.cnblogs.com/chenyushuo/p/4124794.html

總結

以上是生活随笔為你收集整理的初学后缀数组的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。