字尾陣列求不可重疊最長重複子串 POJ 1743

2021-06-03 10:25:27 字數 984 閱讀 7937

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

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

演算法分析:

這題比上一題稍複雜一點。先二分答案,把題目變成判定性問題:判斷是否存在兩個長度為k 的子串是相同的,且不重疊。解決這個問題的關鍵還是利用height 陣列。把排序後的字尾分成若干組,其中每組的字尾之間的height 值都不小於k。例如,字串為「aabaaaab」,當k=2 時,字尾分成了4 組,如圖5所示。

容易看出,有希望成為最長公共字首不小於k 的兩個字尾一定在同一組。然後對於每組字尾,只須判斷每個字尾的sa 值的最大值和最小值之差是否不小於k。如果有一組滿足,則說明存在,否則不存在。整個做法的時間複雜度為o(nlogn)。本題中利用height 值對字尾進行分組的方法很常用,請讀者認真體會。

#define maxn 20010

int wa[maxn],wb[maxn],wv[maxn],wss[maxn];

int r[maxn],sa[maxn];

int cmp(int *r,int a,int b,int l)

/*【倍增演算法o(nlgn)】待排序的字串放在r 陣列中,從r[0]到r[n-1],長度為n,且最大值小於m

使用倍增演算法前,需要保證r陣列的值均大於0。然後要在原字串後新增乙個0號字元

所以,若原串的長度為n,則實際要進行字尾陣列構建的r陣列的長度應該為n+1.所以呼叫da函式時,對應的n應為n+1.

*/void da(int *r,int *sa,int n,int m) else minm = maxm = sa[i];}}

if(ok) else r = mid-1;

}//ans+1的原因是前面的處理是把後乙個減去前乙個的值,所以最後要+1個

if(ans+1<=4)printf("%d\n",0);

else printf("%d\n",ans+1);

}return 0;

}

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

poj 1743 二分答案,把題目變成判定性問題 判斷是否 存在兩個長度為k的子串是相同的,且不重疊。解決這個問題的關鍵還是利用 height陣列。把排序後的字尾分成若干組,其中每組的字尾之間的height值都 不小於k。有希望成為最長公共字首不小於k的兩個字尾一定在同一組。然 後對於每組字尾,只須...

字尾陣列練習1 不可重疊最長重複子串

這道題在之前,一定要先看一下我之前在字尾陣列部落格裡面提到的最長公共字首 poj1743 時間限制 2 sec 記憶體限制 128 mb 提交 207 解決 81 提交 狀態 討論版 命題人 admin 題目描述 然後如果你了解了最長公共字首,那麼我們就提一下這道題和最長公共字首有什麼大關係 求字串...

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

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