後綴數組應用

   今天看了後綴數組的應用,整理一下:

例 1:最長公共前綴
給定一個字符串,詢問某兩個後綴的最長公共前綴。
算法分析:
按照上面所說的做法,求兩個後綴的最長公共前綴可以轉化爲求某個區間上的最小值。對於這個 RMQ 問題(如果對 RMQ 問題不熟悉,請閱讀其他相關資料),可以用 O(nlogn)的時間先預處理,以後每次回答詢問的時間爲 O(1)。所以對於本問題,預處理時間爲 O(nlogn),每次回答詢問的時間爲 O(1)。如果 RMQ 問題用 O(n)的時間預處理,那麼本問題預處理的時間可以做到 O(n)。 

2.2單個字符串的相關問題 
這類問題的一個常用做法是先求後綴數組和 height 數組,然後利用 height數組進行求解

2.2.1重複子串
重複子串:字符串 R 在字符串 L 中至少出現兩次,則稱 R 是 L 的重複子串。


例 2:可重疊最長重複子串
給定一個字符串,求最長重複子串,這兩個子串可以重疊。
算法分析:
這道題是後綴數組的一個簡單應用。做法比較簡單,只需要求 height 數組裏的最大值即可。首先求最長重複子串,等價於求兩個後綴的最長公共前綴的最大值。因爲任意兩個後綴的最長公共前綴都是 height 數組裏某一段的最小值,那麼這個值一定不大於 height 數組裏的最大值。所以最長重複子串的長度就是height 數組裏的最大值。這個做法的時間複雜度爲 O(n)。


例 3:不可重疊最長重複子串(pku1743)
給定一個字符串,求最長重複子串,這兩個子串不能重疊。
算法分析:
這題比上一題稍複雜一點。先二分答案,把題目變成判定性問題:判斷是否存在兩個長度爲 k 的子串是相同的,且不重疊。解決這個問題的關鍵還是利用height 數組。把排序後的後綴分成若干組,其中每組的後綴之間的 height 值都不小於 k。例如,字符串爲“aabaaaab”,當 k=2 時,後綴分成了 4 組,如圖5


容易看出,有希望成爲最長公共前綴不小於 k 的兩個後綴一定在同一組。然後對於每組後綴,只須判斷每個後綴的 sa 值的最大值和最小值之差是否不小於k。如果有一組滿足,則說明存在,否則不存在。整個做法的時間複雜度爲O(nlogn)。

例 4:可重疊的 k 次最長重複子串(pku3261)給定一個字符串,求至少出現 k 次的最長重複子串,這 k 個子串可以重疊。算法分析:這題的做法和上一題差不多,也是先二分答案,然後將後綴分成若干組。不同的是,這裏要判斷的是有沒有一個組的後綴個數不小於 k。如果有,那麼存在k 個相同的子串滿足條件,否則不存在。這個做法的時間複雜度爲 O(nlogn)。

2.2.2子串的個數 

例 5:不相同的子串的個數(spoj694,spoj705)給定一個字符串,求不相同的子串的個數。算法分析:每個子串一定是某個後綴的前綴,那麼原問題等價於求所有後綴之間的不相同的前綴的個數。如果所有的後綴按照 suffix(sa[1]), suffix(sa[2]),suffix(sa[3]), …… ,suffix(sa[n])的順序計算,不難發現,對於每一次新加進來的後綴 suffix(sa[k]),它將產生 n-sa[k]+1 個新的前綴。但是其中有height[k]個是和前面的字符串的前綴是相同的。所以 suffix(sa[k])將“貢獻”出 n-sa[k]+1- height[k]個不同的子串。累加後便是原問題的答案。這個做法的時間複雜度爲 O(n)。

 2.2.3迴文子串 :

如果將字符串 L 的某個子字符串 R 反過來寫後和原來的字符串 R一樣,則稱字符串 R 是字符串 L 的迴文子串。

例 6:最長迴文子串(ural1297)給定一個字符串,求最長迴文子串。算法分析:窮舉每一位,然後計算以這個字符爲中心的最長迴文子串。注意這裏要分兩種情況,一是迴文子串的長度爲奇數,二是長度爲偶數。兩種情況都可以轉化爲求一個後綴和一個反過來寫的後綴的最長公共前綴。具體的做法是:將整個字符串反過來寫在原字符串後面,中間用一個特殊的字符隔開。這樣就把問題變爲了求這個新的字符串的某兩個後綴的最長公共前綴。如圖 6 所示


這個做法的時間複雜度爲 O(nlogn)。如果 RMQ 問題用時間爲 O(n)的方法預處理,那麼本題的時間複雜度可以降爲 O(n)。

2.2.4 連續重複子串連續重複串:

如果一個字符串 L 是由某個字符串 S 重複 R 次而得到的,則稱L 是一個連續重複串。R 是這個字符串的重複次數。

例 7:連續重複子串(pku2406)給定一個字符串 L,已知這個字符串是由某個字符串 S 重複 R 次而得到的,求 R 的最大值。

算法分析:做法比較簡單,窮舉字符串 S 的長度 k,然後判斷是否滿足。判斷的時候,先看字符串 L 的長度能否被 k 整除,再看 suffix(1)和 suffix(k+1)的最長公共前綴是否等於 n-k。在詢問最長公共前綴的時候,suffix(1)是固定的,所以 RMQ問題沒有必要做所有的預處理,只需求出 height 數組中的每一個數到height[rank[1]]之間的最小值即可。整個做法的時間複雜度爲 O(n)。

例 8:重複次數最多的連續重複子串(spoj687,pku3693)給定一個字符串,求重複次數最多的連續重複子串。

算法分析:先窮舉長度 L,然後求長度爲 L 的子串最多能連續出現幾次。首先連續出現1 次是肯定可以的,所以這裏只考慮至少 2 次的情況。假設在原字符串中連續出現 2 次,記這個子字符串爲 S,那麼 S 肯定包括了字符 r[0], r[L], r[L*2],r[L*3], ……中的某相鄰的兩個。所以只須看字符 r[L*i]和 r[L*(i+1)]往前和往後各能匹配到多遠,記這個總長度爲 K,那麼這裏連續出現了 K/L+1 次。最後看最大值是多少。如圖 7 所示。


暫時先整理這麼多,以上內容主要引自許智磊《後綴數組》論文 寫的非常好,有興趣的可以b可以拜讀一下,鏈接我已經發在上篇博客裏了。


發佈了101 篇原創文章 · 獲贊 23 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章