****於
問題描述
給定乙個字串,求出其最長重複子串
例如:abcdabcd
最長重複子串是 abcd,最長重複子串可以重疊
例如:abcdabcda,這時最長重複子串是 abcda,中間的 a 是被重疊的。
直觀的解法是,首先檢測長度為 n - 1 的字串情況,如果不存在重複則檢測 n - 2, 一直遞減下去,直到 1 。
這種方法的時間複雜度是 o(n * n * n),其中包括三部分,長度緯度、根據長度檢測的字串數目、字串檢測。
改進的方法是利用字尾陣列
字尾陣列是一種資料結構,對乙個字串生成相應的字尾陣列後,然後再排序,排完序依次檢測相鄰的兩個字串的開頭公共部分。
這樣的時間複雜度為:生成字尾陣列 o(n),排序 o(nlogn*n) 最後面的 n 是因為字串比較也是 o(n)
依次檢測相鄰的兩個字串 o(n * n),總的時間複雜度是 o(n^2*logn),優於第一種方法的 o(n^3)
對於類似從給定的文字中,查詢其中最長的重複子字串的問題,可以採用「字尾陣列」來高效地完成此任務。字尾陣列使用文字本身和n個附加指標(與文字陣列相應的指標陣列)來表示輸入文字中的n個字元的每個子字串。
首先,如果輸入字串儲存在c[0..n-1]中,那麼就可以使用類似於下面的**比較每對子字串:
這樣,元素a[0]指向整個字串,下乙個元素指向以第二個字元開始的陣列的字尾,等等。如若輸入字串為"banana",該陣列將表示這些字尾:
a[0]:banana
a[1]:anana
a[2]:nana
a[3]:ana
a[4]:na
a[5]:a
由於陣列a中的指標分別指向字串中的每個字尾,所以將陣列a命名為"字尾陣列"
第二、對字尾陣列進行快速排序,以將字尾相近的(變位詞)子串集中在一起
qsort(a, n, sizeof(char*), pstrcmp)後
a[0]:a
a[1]:ana
a[2]:anana
a[3]:banana
a[4]:na
a[5]:nana
第三、使用以下comlen函式對陣列進行掃瞄比較鄰接元素,以找出最長重複的字串:
for(i = 0 ; i < n-1 ; ++i )}printf("%.*s\n",maxlen, a[maxi]);
#include using namespace std;
#define maxchar 5000 //最長處理5000個字元
char c[maxchar], *a[maxchar];
int comlen( char *p, char *q )
int pstrcmp( const void *p1, const void *p2 )
int main(void)
c[n]='\0'; // 將陣列c中的最後乙個元素設為空字元,以終止所有字串
qsort( a, n, sizeof(char*), pstrcmp );
for(i = 0 ; i < n-1 ; ++i )
}printf("%.*s\n",maxlen, a[maxi]);
return 0;
}
最長重複子串(字尾陣列)
時間限制 1000 ms 記憶體限制 3000 kb 描述 對於乙個字串s1,其中s2是他的乙個子串 長度嚴格小於s1長度 如果s2在s1 現次數超過1次,那麼s2就是乙個重複子串,現在的要求是給定s1,請求出他的最長重複子串 如果有多個長度一樣的最長子串,請輸入字典序最小那個串 比如bbbaaac...
最長重複子串 可重複 字尾陣列
時間限制 1000 ms 記憶體限制 3000 kb 描述 對於乙個字串s1,其中s2是他的乙個子串 長度嚴格小於s1長度 如果s2在s1中出現次數超過1次,那麼s2就是乙個重複子串,現在的要求是給定s1,請求出他的最長重複子串 如果有多個長度一樣的最長子串,請輸入字典序最小那個串 比如bbbaaa...
求最長重複子串
主要思路還是求出所有的字尾陣列,對字尾陣列進行排序,這樣所有最接近的字串一定就在相鄰了,只需要比較每個字尾陣列的前後兩個串,就可以求出所有重複的字串,然後比較就可以得到最大的重複串的長度。include include include include include using namespace ...