字尾陣列的應用 最長重複 or回文 子串

2021-07-05 21:15:06 字數 2622 閱讀 4389

link:

問題:比如 weksabcdjklabcdll 最長重複字串為"abcd"

解析:字尾陣列舉例

如下目標字串: bananas 其長度為7,則字尾陣列的長度為7,分別是以b開頭的字串(長度為7),以a開頭的字串(長度為6),以n開頭的字串(長度為5)。。。最後乙個是以s開頭的字串(長度為1)。

字尾[0] bananas

字尾[1] ananas

字尾[2] nanas

字尾[3] anas

字尾[4] nas

字尾[5] as

字尾[6] s

回到正題,查詢一段文字中最長的重複字串。(注意:這不同於演算法設計課中常講的兩個字串的最長公共子串行問題(lcs),lcs問題的最長公共字串可以不是連續的)

最樸素的演算法是,讓字尾陣列之間兩兩比較,找出最長的公共字串(注意,這裡的最長的公共字串必須是以首字元參與匹配的,如果首字母都不匹配,那麼長度為0,eg字尾[0]和字尾[1]之間的首字母不匹配,則兩者的最長公共字串長度為0.。),但是時間複雜度為o(n^2).

該思想基於以下兩個資訊:

1)如果存在乙個最長的重複字串,那麼兩個字串均是來自文字串不同的字尾,但這兩個字尾有相同的字首!(這個字首也就是重複字串了)

2)既然最終結果的字尾肯定擁有相同的字首,那麼我就沒有必要讓全部字尾之間兩兩比較,而僅僅比較具有相同的字首(首字母)的字尾即可!這可以大大的減少比較的次數,提高效率。

所以,演算法的流程是,先將字尾陣列字母排序(其實就是對字元陣列排序),然後順次比較(避免了兩兩比較)即可。

字尾[0] ananas

字尾[1] anas

字尾[2] as

字尾[3] bananas

字尾[4] nanas

字尾[5] nas

字尾[6] s

字尾[2]和字尾[3]不用比較(a!=b) ……

字尾[5]和字尾[6]不用比較(n!=s)

so,最終的比較結果是 字尾[1]和字尾[2] 之間存在最長公共字串"ana"在字尾[0]裡。

#include 

#include 

//qsort

#include <

string

.h>

#define maxchar 1000 /

/最長處理1000個字元

char c[maxchar]

,*a[maxchar]

;int comlen( char *p, char *q )

int pstrcmp(

const void *p1,

const void *p2 )/*

** find longest repeat string

by suffix array

*"weksabcdjklabcdgg" 最長重複字串為"abcd"*/

char * lrs_sufarr(

)c[n]='

\0';

/* 列印字尾陣列,不是必須的。*

/for

(i = 0; i < n;

++i)

printf(

"%d: %s\n"

, i+1, a[i]);

qsort( a, n, sizeof(char*

), pstrcmp );/

/qsort後,n個字尾陣列[i.

.n-1]就是排好序的了.

printf(

"------ after sort------\n");

for(i = 0; i < n;

++i)

printf(

"%d: %s\n"

, i, a[i]);

//在字尾陣列中,找出最長重複字首的,即是最長重複子串

for(i=0; i < n-1;

++i )}}

//printf(

"\nselect first %d from:%s\n"

, maxlen, a[maxi]);

*(a[maxi]

+ maxlen)='

\0';

printf(

"max repeat str: %s\nwith length of %d.\n"

, a[maxi]

, maxlen)

;return a[maxi];}

字尾陣列的應用:

上面的**新增乙個height陣列,

temp = comlen( a[i], a[i+1] ); 寫成

height[i] = comlen( a[i], a[i+1] ); //0<=i最長公共字首

給定乙個字串,詢問某兩個字尾的最長公共字首。   

直接套用,ret = min(height[i])    k字尾樹里有重要意義。

例 2 :可重疊最長重複子串

給定乙個字串,求最長重複子串,這兩個子串可以重疊。   

// ret = max(height[i])  0<=i

例 3 :最長回文子串

將整個字串反過來寫在原字串後面,中間用乙個特殊的字元隔開。這樣就把問題變為了

求這個新的字串的某兩個字尾的最長公共字首。

eg:abcbaebf  ---->  abcbaebf#fbeabcba

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

時間限制 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...

字尾陣列求最長重複子串

於 問題描述 給定乙個字串,求出其最長重複子串 例如 abcdabcd 最長重複子串是 abcd,最長重複子串可以重疊 例如 abcdabcda,這時最長重複子串是 abcda,中間的 a 是被重疊的。直觀的解法是,首先檢測長度為 n 1 的字串情況,如果不存在重複則檢測 n 2,一直遞減下去,直到...