尾碼數組詳解+模板

來源:互聯網
上載者:User

標籤:條件   efi   複雜   color   ios   cstring   開始   out   表示   

尾碼數組注

SA[] 第幾名是誰

尾碼數組:尾碼數組 SA 是一個一維數組, 它儲存 1..n 的某個排列 SA[1] ,SA[2],……,SA[n],並且保證 Suffix(SA[i]) < Suffix(SA[i+1]),1≤i<n 。也就是將 S 的 n 個尾碼從小到大進行排序之後把排好序的尾碼的開頭位置順次放入 SA 中。

Rank[] 誰是第幾名名次數組:名次數組 Rank[i]儲存的是 Suffix(i)在所有尾碼中從小到大排列的“名次 ” 。

r[]:未經處理資料j當前字串的長度,每次迴圈根據2個j長度的字串的排名求得2j長度字串的排名.

y[]:指示長度為2j的字串的第二關鍵字的排序結果,通過儲存2j長字串的第一關鍵字的下標進行指示.

wv[]:2j長字串的第一關鍵字的排名序號.

ws[]:計數數組,計數排序用到.

x[]:一開始是未經處理資料r的拷貝(其實也表示長度為1的字串的排名),之後表示2j長度字串的排名.

p:不同排名的個數.

片段1.對長度為1的字串進行排序(函數的第一步)
for(i=0;i<m;i++) ws[i]=0;for(i=0;i<n;i++) ws[x[i]=r[i]]++;for(i=1;i<m;i++) ws[i]+=ws[i-1];for(i=n-1;i>=0;i--) sa[--ws[x[i]]]=i;

 

①用的是基數排序,也可以使用其它的排序

②r[]儲存原本輸入的字串,x[]是對r[]的ASCII呈現(便於排序)

③m是一個估計數字,代表ASCII最大值,在迴圈中做邊界

④n在這裡是字串的長度+1,後面的加加減減有所體現(貌似不介意直接用字串的長度)

⑤最後一行比較難懂,但實踐證明它確實是正確的,sa[i]=j表示第i名是j。

ws[i]是對第i及之前字元出現次數的累加,越往後ws[i]越大,而且對應的字元數值越大,舉個例子,如果某一字串為aaabaa,則a出現的次數為5,b出現的次數為1,按上述原理,可以看做ws[a]=5,ws[b]=6,固然a都在前5名,b在第六名。

對aabaaaab進行輸出後為801345627,按照sa的定義對應起來

aabaaaab ~

23845679 1  非常正確

理解了這個,最後一行就能明白了

2.進行若干次基數排序

因為前面排序的名次可能有重複,所以要再進行若干次,直到所有的名次都不再相同

for(j=1,p=1; p<n; j*=2,m=p){      for(p=0,i=n-j; i<n; i++) y[p++]=i;      for(i=0; i<n; i++) if(sa[i]>=j) y[p++]=sa[i]-j;      for(i=0; i<n; i++) wv[i]=x[y[i]];      for(i=0; i<m; i++) Ws[i]=0;      for(i=0; i<n; i++) Ws[wv[i]]++;      for(i=1; i<m; i++) Ws[i]+=Ws[i-1];      for(i=n-1; i>=0; i--) sa[--Ws[wv[i]]]=y[i];      for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1; i<n; i++)           x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;}

 

相對於上面函數的第一步來說,這一坨代碼更加複雜了

①從最外層迴圈可以看出,j是處於倍增狀態的,代表正在比較的每一小段字串的長度

②迴圈內的第一行,迴圈了j-1次,是對後面幾個數的提前處理(其第二關鍵字都為0)

 

即所有加0的數

③第二行,再翻上去看一眼sa的作用。首先要明白這一行拋棄了一些東西,

 

由於是對第二關鍵字的排序,第一關鍵字先不看,所以有一條件if(sa[i]>=j)

這條語句後面y[p++]=sa[i]-j,要減去j也是因為這個

到這裡,第二關鍵字的排序就完成了

 

④開始第一關鍵字的排序

假設需要排序的數為92 71 10 80 63 90

那麼y[]=3 4 6 2 1 5 即對第二關鍵字排序後名次遞增所對應的序號

      x[]=10 80 90 71 92 63 即對第二關鍵字排序的結果

for(i=0; i<n; i++) wv[i]=x[y[i]];將x[]數組拷貝到wv[]中

⑤剩下的基數排序就與對長度為1的字串進行排序一樣了

完整的代碼(參考理解)
#include <cstdio>#include <iostream>#include <cstring>#define  LL long long#define  ULL unsigned long longusing namespace std;const int MAXN=100010;//以下為倍增演算法求尾碼數組 int wa[MAXN],wb[MAXN],wv[MAXN],Ws[MAXN];int cmp(int *r,int a,int b,int l){return r[a]==r[b]&&r[a+l]==r[b+l];}/**< 傳入參數:str,sa,len+1,ASCII_MAX+1 */ void da(const char r[],int sa[],int n,int m){      int i,j,p,*x=wa,*y=wb,*t;       for(i=0; i<m; i++) Ws[i]=0;      for(i=0; i<n; i++) Ws[x[i]=r[i]]++;//以字元的ascii碼為下標       for(i=1; i<m; i++) Ws[i]+=Ws[i-1];      for(i=n-1; i>=0; i--) sa[--Ws[x[i]]]=i;      /*cout<<"SA"<<endl;;      for(int i=0;i<n+1;i++)cout<<sa[i]<<‘ ‘;*/      for(j=1,p=1; p<n; j*=2,m=p)      {            for(p=0,i=n-j; i<n; i++) y[p++]=i;             for(i=0; i<n; i++) if(sa[i]>=j) y[p++]=sa[i]-j;            for(i=0; i<n; i++) wv[i]=x[y[i]];            for(i=0; i<m; i++) Ws[i]=0;            for(i=0; i<n; i++) Ws[wv[i]]++;            for(i=1; i<m; i++) Ws[i]+=Ws[i-1];            for(i=n-1; i>=0; i--) sa[--Ws[wv[i]]]=y[i];            for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1; i<n; i++)                  x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;      }      return;}int sa[MAXN],Rank[MAXN],height[MAXN];//求height數組/**< str,sa,len */void calheight(const char *r,int *sa,int n){      int i,j,k=0;      for(i=1; i<=n; i++) Rank[sa[i]]=i;      for(i=0; i<n; height[Rank[i++]]=k)            for(k?k--:0,j=sa[Rank[i]-1]; r[i+k]==r[j+k]; k++);      // Unified      for(int i=n;i>=1;--i) ++sa[i],Rank[i]=Rank[i-1];}char str[MAXN];int main(){      while(scanf("%s",str)!=EOF)      {            int len=strlen(str);            da(str,sa,len+1,130);            calheight(str,sa,len);            puts("--------------All Suffix--------------");            for(int i=1; i<=len; ++i)            {                  printf("%d:\t",i);                  for(int j=i-1; j<len; ++j)                        printf("%c",str[j]);                  puts("");            }            puts("");            puts("-------------After sort---------------");            for(int i=1; i<=len; ++i)            {                  printf("sa[%2d ] = %2d\t",i,sa[i]);                  for(int j=sa[i]-1; j<len; ++j)                        printf("%c",str[j]);                  puts("");            }            puts("");            puts("---------------Height-----------------");            for(int i=1; i<=len; ++i)                  printf("height[%2d ]=%2d \n",i,height[i]);            puts("");            puts("----------------Rank------------------");            for(int i=1; i<=len; ++i)                  printf("Rank[%2d ] = %2d\n",i,Rank[i]);            puts("------------------END-----------------");      }      return 0;}

 

尾碼數組詳解+模板

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.