字符串----不可重疊的最長重複子串

題目:給定一個字符串,求最長重複子串,這兩個子串不能重疊。例如,str = "acdcdcdcd",則不可重疊的最長子串爲"cdcd"。數組

思路:二分枚舉+height數組分組。這道題的思想很巧妙,後面要仔細推敲。先二分答案,把題目變成斷定性問題:判斷是否存在兩個長度爲k的子串是相同的,且不重疊。解決這個問題的關鍵仍是利用height數組。把排序後的後綴分紅若干組,其中每組的後綴之間的height值都不小於k。例如,字符串爲「aabaaaab」,當k=2時,後綴分紅了4組,如圖所示。spa

  

  容易看出,有但願成爲最長公共前綴不小於k的兩個後綴必定在同一組。而後對於每組後綴,只須判斷每一個後綴的sa值的最大值和最小值之差是否不小於k。若是有一組知足,則說明存在,不然不存在。整個作法的時間複雜度爲O(nlogn)。3d

代碼:code

 

 1 public class MaxRepeatSubString2 {  2 
 3     public static void main(String[] args) {  4         int res = maxRepeatSubString2("1x23231923263");  5         System.out.println(res);  // 輸出 3
 6  }  7     
 8     /**
 9  * 不容許交叉 10  * 11  * @param src 12  * @return
13      */
14     public static int maxRepeatSubString2(String src) { 15         SuffixArray.Suff[] sa = SuffixArray.getSa2(src); 16         int[] height = SuffixArray.getHeight(src, sa); 17         int l = 0; 18         int r = height.length; 19         int ans = 0; 20         while (l <= r) { 21             int mid = l + ((r - l) >> 1);// check的重疊長度
22             if (check(height, sa, mid)) { 23                 if (mid == height.length / 2) { 24                     return mid; 25  } 26                 l = mid + 1; 27                 ans = mid; 28                 // return mid;
29             } else { 30                 r = mid - 1; 31  } 32  } 33         return ans; 34  } 35     
36     /**
37  * 用len將height分組,小於組和大於等於組交替 38  * 在大於組中更新最大最小原始小標,大轉小的時候檢查上一個大於組是否知足不重疊 39  * 在小於組中,只需持續地將原始下標付給max和min,這樣小轉大的時候,能夠保留小於組最後一個元素的下標 40      */
41     private static boolean check(int []height,SuffixArray.Suff[]sa,int len){ 42         int minIndex = sa[0].index; 43         int maxIndex = sa[0].index; 44         for(int i = 1;i<height.length;i++){ 45             int index = sa[i].index; 46             if(height[i]>=len){ // lcp 大於 len
47                 minIndex = Math.min(minIndex,index); 48                 maxIndex = Math.max(maxIndex, index); 49             } else { 50                 if (maxIndex - minIndex >= len) { 51                     return true; 52  } 53                 maxIndex = index; 54                 minIndex = index; 55  } 56  } 57         return (maxIndex - minIndex) >= len; 58  } 59 
60 }

   在此基礎上稍加改動能夠完成至少出現K次的最長重複子串(可重疊)的題目blog

相關文章
相關標籤/搜索