字尾陣列的應用

2021-07-09 12:23:02 字數 2332 閱讀 6760

1. 求乙個字串所有不同的子串個數(子串意味著是連續的)。比如「abaaba」,它的字串包括:a, b, aa, ab, ba, aba, baa,  aab, abaa, baab, aaba, abaab, baaba, abaaba。這個就可以用字尾陣列的結果求解。

首先,我們知道sa陣列,裡面是排好序的所有字尾,運用字尾的想法就把子串進行了第一次劃分。

然後,對於每乙個字尾串,找出他們所有的字首串,這就進行了第二次劃分,所有的子串就出來了,假設乙個字尾串長度為n,則它一共有n個字首串。所有的字尾串的字首個數相加,結果就出來了。這裡面,因為有些字尾之間有公共字首,公共字首部分構成的串就重複了,要減掉的個數正好是最長公共字首的長度,也就是上面網頁裡的height陣列。所以,結果很容易就出來了。

int total = 0;

for (int i = 0; i < n; i++)

total += n - i - height[sa[i]];

2. 求乙個字串中所有不同子串中,按字典序的第k個子串。

這個也可以用字尾陣列求,因為sa陣列就是按字典序排列好的。對於某個字串sa[i]來說,按字典序,它的所有字首肯定比它本身要小的,去掉最長公共字首部分,順次往下找就行,跳乙個字元就是乙個排名。簡略**如下:

int total = 0;

int i, end;

for (i = 0; i < n; i++)

total += acc;

}

3. 求所有子串,和2類似。

4. 求可重疊最長重複子串。重複子串就是兩個子串完全相同,這兩個子串是可以有相交的部分的。最長的就是公共字首值最大的,也就是height陣列的最大值。

5.  求不可重疊最長重複子串。這裡兩個子串不能有相交部分。試想一下,這兩個子串還是必須包含在兩個字尾串裡面,有公共的字首,那才能相等啊。只是這兩個字尾串在原字串中的位置之間要有一定距離,這個距離要大於或等於二者公共字首長度,二者才不會重複。**如下:

int maxlen = 0, beg=0;

for (int i = 0; i < n; i++) }

int end = maxlen + beg;

for (int j = beg; j < end; ++j)

cout << ch[j] <<" ";

cout << endl;

6. 

給定乙個字串str,已知這個字串是由某個字串s重複r

次而得到的,

求r的最大值。(pku2406)。首先,如果str裡不存在題目中所要求的串,那整個str是乙個s,此時r=1。設str長度為n, 串s的長度為len,len取值為[1,n],遍歷列舉。要找到題目要求的串,必須滿足:1. n%len=0,即要能整除;2. 串s在原串str中第一次出現處的字尾陣列和第二次出現處的字尾陣列...第r次出現處的字尾陣列,最長公共字首就是這個串s。這裡我只進行第一次和第二次公共字首判斷。**如下:

int r=0;

for (int len = 1; len < n; ++len) }

cout << r << endl;

這是有更簡單,耗時少的解法,用kmp演算法的next陣列。對整個字串str求next陣列,如果有重複,str最後乙個字元的next值就是前乙個串s的結尾。串s的長就是n-next[n-1]。
int len=n-next[n-1];

if(n%len==0)

cout《這個版本和嚴蔚敏老師教材上的基本一樣,只是乙個從-1開始,乙個從0開始。它是經過優化之後 的,用這個版本解決我們這裡的問題肯定是不行的。還有乙個沒優化版本,嚴老師的書上也有乙個沒優化的版本,這是可以解決我們上面問題的:

void makenext(const char pattern, int next)

next[q] = k;

}}

注意這裡next的含義與上面**就不一樣了。它是

長度為1到n的字串pattern的前字尾的最大公共長度。比如"abaabaaba"第一字元a它沒有前字尾,也就沒有公共部分,所以next[0]為0。前二字元"ab",字首為a字尾為b, 二者也沒公共部分...所以,next[1]也為0。詳細的解釋看

這裡吧,又學習了一種新的解釋kmp演算法的方法,不得不說演算法到處都是坑啊。像前面說的,這個是沒優化的,優化的原因可以參考嚴老師教材,也可以看這裡。還有乙個現象:在未優化版本中,求next值的模式串是可以有重疊部分的,(優化後的版本沒這種情況),所以,如果乙個串str由m個s串重複組成,則最後乙個字元的next值正好是串str除去第乙個s串的長度,所以本題上面的解法就顯而易見了。具體實現時下標0, -1, +1,-1什麼的要注意。

字尾陣列的應用

本文參考了 字尾陣列 處理字串的有力工具 子串 字串s 的子串r i.j i j,表示r 串中從i 到j 這一段,也就是順次排列r i r i 1 r j 形成的字串。字尾 字尾是指從某個位置i 開始到整個串末尾結束的乙個特殊子串。字串r 的從第i 個字元開始的字尾表示為suffix i 也就是 s...

字尾陣列的應用一

1 可重疊的最長連續子串 題意 給乙個字串,問重複出現的連續的子串中最長的,重複的子串可以有重疊的部分,若結果不止乙個則輸出字典序最小的 例 對於字串 abcabcabc 結果為 abcabc 對於字串 abcdggabc 結果為 abc 解法 找到height陣列中最大的,假設height i 是...

字尾陣列學習與應用

sa i 即,排名為i的字尾的起點下標 rank i 即,第i個字尾的排名 height i 即,sa i 和sa i 1 的最長公共字首 h i 即,height rank i 即第i個字尾與前一名的最長公共字首 結論一 定義 lcp i,j lc p su ffix sa i s uffi x ...