【進階】後綴數組之精髓——height數組

如果想了解更多內容,歡迎關注我的微信公衆號:信息學競賽從入門到巔峯。

戳這裏獲得更好的閱讀體驗哦!

 

上期我們介紹了後綴數組中代碼最難寫的一部分,今天我們來講解一下後綴數組中最精髓的一部分——height數組的求解。

【進階】字符串問題一大利器——後綴數組詳解(附上sa數組求法的講解)

幾個共識

和之前一樣,爲了後文方便講解,我們先來達成幾個共識。

1、height[i]表示後綴sa[i-1]和後綴sa[i]的最長公共前綴。換句話說,height數組表示排名相鄰的兩個後綴的最長公共前綴。

2、h[i]表達第i個後綴和排名在他之前一位的後綴的最長公共前綴,即

性質及證明

防止證明過程中公式排版出錯,這裏仍然採用圖片的形式講解。

求解height

我們很容易想到一種樸素的暴力算法,直接在每兩個排名相鄰的後綴之間枚舉求解。但是這種算法最壞情況下的複雜度是O(N^2)的,而且完全沒有利用後綴數組的性質。

下面,我們來講解一種時間複雜度爲O(N)的巧妙求法。

利用h數組的性質,我們按照排名的順序來求解height數組。每次先把長度減1後,循環暴力擴展,並且把求出來的h[i]拷貝到height[rank[i]]即可。

由於字符串的長度最大爲N,最多進行N次減1操作,所以總計算次數是O(N)級別的。

Code

void height_get(int *r,int n) {
//r爲字符串原串,n爲字符串長度。
//此處的字符串爲添加最小元素後的字符串。
    int k=0;
    for (int i=0;i<n;++i)rank[sa[i]]=i;
    for (int i=0;i<n;++i)
    {
        if (k)k--;
        int j=sa[rank[i]-1];
        while (r[i+k]==r[j+k])k++;
        height[rank[i]]=k;
    }
}//求最長公共前綴,利用h[i]>=h[i-1]-1

寫在最後

後綴數組算法的重點在於求解sa數組、rank數組和height數組。有了這三個數組,我們就可以在字符串的世界自由玩耍了【滑稽】。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章