後綴數組之多字符串問題

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

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

 

在多字符串問題上,後綴數組是否仍然有優秀的表現呢?

答案顯然是肯定的。

 

最長公共子串

Problem:給定兩個字符串S和T,求這兩個字符串的最長公共子串。

Solution:容易發現,一個字符串的子串,一定是該字符串的每個後綴的前綴。所以,求兩個字符串的最長公共子串,只需要找這兩個字符串的後綴的最長公共前綴就行了。

但是,問題在於如何對兩個字符串使用後綴數組呢?

這裏有一個小技巧。我們可以用一個在兩個字符串中都沒有出現的字符(例如特殊字符等)將這兩個字符串連接到一起(這裏是爲了對新字符串進行截斷),如下圖所示:

這樣我們就把問題轉化成:給定一個字符串,求這個字符串前一部分的後綴後一部分的後綴的最長公共前綴的長度。

由height數組的性質,我們只需判斷相鄰的兩個後綴是否屬於新字符串的不同部分。如果是,就能用該位置的height來更新答案。

下面是一個例子:

爲什麼不用把前半部分的後綴和後半部分的後綴兩兩求最長公共前綴呢?我們知道從一個後綴a開始,往後求a和任意一個後綴的最長公共前綴(設長度爲L),L會小於之間任何一個height的值。所以,當一個後綴向後匹配超過一個後綴是沒有必要的。

 

長度不小於k的公共子串的個數

Problem:給定兩個字符串S和T,求這兩個字符串中長度不小於k的公共子串的個數。其中,公共子串可以相同。

Solution:先考慮一個暴力的方法:先將字符串S和T用一個沒出現過的字符連接起來得到新字符串A,然後求A的後綴數組,對於每一個S的後綴(即A的前半部分的後綴),我們可以統計它和每一個T的後綴的最長公共前綴。

這樣的複雜度極高,那麼有沒有什麼優化的方法呢?

我們可以嘗試對A的後綴數組進行順序遍歷,遍歷到一個S的後綴時,統計這個後綴與之前出現過的T的後綴的最長公共前綴。考慮height數組的性質,對於一個後綴sa[j],sa[i] (1<=i<j) 和sa[j]的最長公共前綴隨i的增大而增大。

所以,我們可以用一個數組q來維護處理到sa[j]時,出現過的T的後綴與sa[j]的最長公共前綴。通過前面的分析,我們知道數組q是單調遞增的。所以,每次新掃過一個後綴,我們可以用二分的方法來更新數組q中的值。如果當前這個後綴是T的後綴,那麼我們就把這個後綴加入數組q。否則就計算數組q中每一個後綴與當前後綴的最長公共前綴(即q數組中每一個元素的和)。

 

總結

我們介紹了後綴數組在兩個字符串問題上的應用。多個字符串與之類似,我們只需要把多個字符串用沒出現過的字符連接起來,求解後綴數組,然後依題意來判斷即可。

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