演算法合集之《字尾陣列 處理字串的有力工具》

2021-07-10 22:33:43 字數 2266 閱讀 6234

字尾陣列:

sa[i]:表示排名第i個的首字母位置

rank[i]:第i個數的排名

height[i]:sa[i]和sa[i-1]的最長公共字首

suffix(j) 和suffix(k) 的最長公共字首為height[rank[j]+1],

height[rank[j]+2], height[rank[j]+3], … ,height[rank[k]]中的最小值。

由於是求區間最小值,所以還可以往上面套乙個rmq

1.不可重疊最長重複子串(pku1743)

給你一串數字,求它們最長的重複(公差相同)子串行,且兩個子串行不相交

我們可以向二分列舉ans長度,如果能找到兩個height>=ans,而且通過sa判斷兩個的間距》=ans,則說明這個答案合適。

解題報告

2.可重疊的k 次最長重複子串(pku3261)

最開始想到是二分列舉ans長度,從頭到尾找出height>=ans的總數,但是這要容易出現問題,無法保證是同乙個串重複出現的。所以應該分組討論,即連續》=ans的長度(可以保證它們的字首是相同的)。

解題報告

3.不相同的子串的個數(spoj694,spoj705)

可以轉換成求相同子串的個數,而相同子串的個數可以轉換成公共字首的個數

->len*(len+1)/2-sum(height)

解題報告

4.最長回文子串(ural1297)

分兩種情況,一是回文子串的長度為奇數,二是長度為偶數。兩種情況都可以轉化為求乙個字尾和乙個反過來寫的字尾的最長公共字首。具體的做法是:將整個字串反過來寫在原字串後面,中間用乙個特殊的字元隔開。這樣就把問題變為了求這個新的字串的某兩個字尾的最長公共字首。

5.連續重複子串(pku2406)

需要判斷rank[0]和rank[k]是否為n-k

(因為如果相等,0~k = k+1~2*k+1 .... 遞推下去 整個串是0~k的子串不斷重複得到)

所以我們可以先處理出每個到rank[0]的位置(從rank[0]的位置往兩邊掃一遍),然後列舉判斷一下即可

解題報告

6.重複次數最多的連續重複子串(spoj687,pku3693)

首先,列舉l(用來重複的長度),判斷suff[i],suff[i+l],如果公共字首k%l != 0,則說明這個長度不合適,修改後再進行判斷。

於是考慮k%l,可以看成兩個串之間多了k%l個字元,但可以看成前面少了m = l-k%l,所以把兩個串都往前移動m個字元,於是成了求 l-i-m,l-m的情況,如果還是不合適->捨棄

然後記錄最大次數cnt和符合條件的所有解a最後進行判斷,因為要求字典序最小,所以從sa[1]開始判斷

解題報告

7.最長公共子串(pku2774)

相當於求兩個字串所有字尾的最長公共字首,所以我們可以把兩個字串用乙個特殊字元間隔連起來然後找出最大的height,同時通過sa陣列判斷一下它們是否

解題報告

8.長度不小於k 的公共子串的個數(pku3415)

從頭到尾列舉height,如果當前是屬於a串,則加上前面所有屬於b串的height-k+1.對於b串同理.

兩個串之間的公共字首是它們之間所有的最小值,所以用棧維護一下,保證棧裡是單調遞增的,這樣對於新增的串只需要處理其中height大於它的一部分即可.

解題報告

9.不小於k 個字串中的最長子串(pku3294)

求的是最長公共子串,所以考慮 二分答案len+判斷

因為要判斷是否為x個串共享所以對height進行分組,即height陣列中各個連續≥len

的集合,然後對每個組進行判斷,看書否能找到x+1個不同的**。

滿足條件就記錄 子串的起始位置和長度

1.串之間的間隔符號不能相同

2.因為有100個串,所以已經佔據了0-99,所以字串的資訊轉換成int的時候

必需是從100開始

解題報告

10.每個字串至少出現兩次且不重疊的最長子串(spoj220)

因為是求的最長子串,所以考慮二分長度len

然後我們需要對其進行判斷,對於每乙個連續大於等於len的height(分組討論)

記錄各個串中的情況,因為要判斷不是重疊的,所以對於每個串,我們記錄

它滿足height>=len的最大最小位置

如果所有串的max-min >= len 則說明存在長度為len的子串在每個串都有出現兩次且不重疊

解題報告

hdu5558

從[1,n]對於每個i,求suff[j](j < i)與suff[i]的最長公共字首,如果有多個,取最小的那個

解題報告

字串演算法之後綴陣列

字串演算法一直是我最不願碰的東西,包括dp。ababs 中所有的字尾串為 ababs babs abs bs s 我們按照字典序排列即為 ababs abs babs bs s 而字尾陣列就是用來求字尾的字典序的 sa i 為排名為i的字尾第乙個字元在主串裡的位置.譬如上面的例子 sa 1 1,sa...

字尾陣列 用字尾處理字串

字尾陣列處理的是文字串。我們將文字串的每一條字尾拿出來,按照字典序排序,然後就可以處理字尾陣列了。字尾陣列sa i 表示的就是排名第i位的字尾的第乙個字元所在下標。這可能有點繞口,所以我們用樣例解釋一下,如對於文字串ababa,則字尾為ababa,baba,aba,ba,a,我們排序後就是 a,ab...

字串匹配之後綴樹

試想有這樣乙個問題,有乙個長度為n的字串a n值很大 還有乙個模式串b,b的長度為m n m很大,說明b只是乙個小片段 此時需要判斷b是否是a的字串。如果我們使用kmp演算法的話,那麼複雜度為o n 對a串進行k次模式匹配的話就是ko n 此時為了降低複雜度,我們可以考慮預處理長字串a,是的,如果我...