求最長可重疊重複子串

2021-06-26 06:28:00 字數 2443 閱讀 6378

問題描述

給定乙個字串,求出其可重疊最長重複子串

例如: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]中,那麼就可以使用類似於下面的**比較每對子字串:

1.int main(void)  

2.  

17.       }  

18.   }  

19.   ......  

20.   ......  

21.   ......  

22.   return 0;  

23.}  

當作為comlen函式引數的兩個字串長度相等時,該函式便返回這個長度值,從第乙個字元開始:

1.int comlen( char *p, char *q )  

2.  

由於該演算法檢視所有的字串對,所以它的時間和n的平方成正比。下面便是使用「字尾陣列」的解決辦法。

如果程式至多可以處理maxn個字元,這些字元被儲存在陣列c中:

1.#define maxchar 5000 //最長處理5000個字元  

2.char c[maxchar], *a[maxchar];  

在讀取輸入時,首先初始化a,這樣,每個元素就都指向輸入字串中的相應字元:

1.n = 0;  

2.while( (ch=getchar())!='\n' )  

3.  

7.c[n]='\0';     // 將陣列c中的最後乙個元素設為空字元,以終止所有字串  

這樣,元素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函式對陣列進行掃瞄比較鄰接元素,以找出最長重複的字串:

1.for(i = 0 ; i < n-1 ; ++i )  

2.  

9.}  

10.printf("%.*s\n",maxlen, a[maxi]);  

完整**:

#include#include#include#define n 5000

char c[n],*a[n];

int cmp(const void *a ,const void *b)

int comlen(char *p,char *q)

int main()

c[n]='\0';   // 將陣列c中的最後乙個元素設為空字元,以終止所有字串

qsort(a,n,sizeof(a[0]),cmp);

for(i=0;imaxlen)

}printf("%d %s\n",maxlen,a[maxi]);

return 0;

}

kmp求法:

#include#include#define n 1000

int next[n];

char str[n];

void getnext(char *str)

}printf("%d\n",maxlen);

}return 0;

}

最長可重疊的重複子串

題目大意 給定乙個字串,求它的最長可重疊的重複子串的長度 思路 求出height陣列之後,輸出最大值即可。因為最長可重疊的重複子串一定是在相鄰兩個字尾的最長公共字首,即height,而要求最大值,輸出height最大值即可 include include define max a,b a b?a b...

最長可重疊的重複子串(2)

勇幸 thinking 首先這是乙個單字串問題。子字串r 在字串l 中至少出現兩次,則稱r 是l 的重複子串。重複子串又分為可重疊重複子串和不可重疊重複子串,這裡只是簡單討論最長可重疊的重複子串,給出基本演算法和基於字尾陣列的演算法 關於字尾陣列,這裡也只是用最簡單的形式實現,對於字尾陣列的倍增演算...

最長重複子串(可重疊) 字尾陣列

找了半天終於找到乙個可以提交的地方。題解 任何乙個重複子串,都必然是某兩個字尾的最長公共字首。因為,兩個字尾的公共字首,它出現在這兩個字尾中,並且起始位置時不同的,所以這個公共字首必然重複出現兩次以上 可重疊 而任何兩個字尾的最長公共字首為某一段height值中的最小值,所以最大為height值中的...