LeetCode 1044. Longest Duplicate Substring

原题链接在这里:https://leetcode.com/problems/longest-duplicate-substring/

题目:

Given a string s, consider all duplicated substrings: (contiguous) substrings of s that occur 2 or more times. The occurrences may overlap.

Return any duplicated substring that has the longest possible length. If s does not have a duplicated substring, the answer is "".

Example 1:

Input: s = "banana"
Output: "ana"

Example 2:

Input: s = "abcd"
Output: ""

Constraints:

  • 2 <= s.length <= 3 * 104
  • s consists of lowercase English letters.

题解:

We could guess a length, and check if there is duplicate.

If there is, then we could guess a bigger one. Otherwise, a smaller one.

How to check duplicates with given length. Use rolling hash.

"abcd", len = 3. when "abc" we have a hash, when it comes to "d", first decrease "a" then add "d" hash.

Time Complexity: O(nlogn). n = s.length().

Space: O(n).

AC Java:

 1 class Solution {
 2     int m = 1000000007;
 3     int base = 26;
 4     
 5     public String longestDupSubstring(String s) {
 6         if(s == null || s.length() == 0){
 7             return s;
 8         }    
 9         
10         int [] nums = new int[s.length()];
11         for(int i = 0; i < s.length(); i++){
12             nums[i] = (int)(s.charAt(i) - 'a');
13         }
14         int l = 1;
15         int r = s.length();
16         while(l <= r){
17             int mid = l + (r - l) / 2;
18             if(isValid(s, mid, nums) != -1){ 
19                 l = mid + 1;
20             }else{
21                 r = mid - 1;
22             }
23         }
24         
25         int start = isValid(s, l - 1, nums);
26         return s.substring(start, start + l - 1);
27     }
28     
29     private int isValid(String s, int len, int [] nums){
30         int n = s.length();
31         Map<Long, List<Integer>> map = new HashMap<>();
32         long hash = 0;
33         for(int i = 0; i < len; i++){
34             hash = (hash * base + (s.charAt(i) - 'a')) % m;
35         }
36         
37         map.put(hash, Arrays.asList(0));
38         
39         // pre-compute deduction multiplier
40         long mul = 1;
41         for(int i = 0; i < len; i++){
42             mul = (mul * base) % m;
43         }
44         
45         for(int start = 1; start < n - len + 1; start++){
46             hash = (hash * base - nums[start - 1] * mul % m + m) % m;
47             hash = (hash + nums[start + len - 1]) % m;
48             List<Integer> list = map.get(hash);
49             if(list != null){
50                 // There are equal hash before
51                 String cur = s.substring(start, start + len);
52                 for(int ind : list){
53                     if(s.substring(ind, ind + len).equals(cur)){
54                         return ind;
55                     }
56                 }
57             }
58             
59             map.putIfAbsent(hash, new ArrayList<Integer>());
60             map.get(hash).add(start);
61         }
62         
63         return -1;
64     }
65 }

类似Longest Repeating Substring.

posted @ 2022-08-08 06:01  Dylan_Java_NYC  阅读(46)  评论(0编辑  收藏  举报