Longest Duplicate Substring - Complete Solution Guide
Longest Duplicate Substring is LeetCode problem 1044, a Hard level challenge. This complete guide provides step-by-step explanations, multiple solution approaches, and optimized code in python3, java, cpp, c.
Problem Statement
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 * 10 4 s consists of lowercase English letters.
Detailed Explanation
The problem asks us to find the longest substring that appears at least twice within a given string `s`. The occurrences of the substring can overlap. If no such substring exists, return an empty string.
Solution Approach
The solution uses a binary search approach to find the length of the longest duplicate substring. For a given length `L`, it uses a rolling hash function to compute the hash values of all substrings of length `L` in O(n) time. It stores these hash values in a hash map (or unordered map), along with the starting indices of the corresponding substrings. During the rolling hash process, if a hash value is already present in the hash map, it checks for actual string equality to confirm the substring duplication and returns the index. The binary search continues until the maximum possible length of the duplicate substring is found.
Step-by-Step Algorithm
- Step 1: Initialize `low` to 1 and `high` to `n - 1`, where `n` is the length of the input string `s`. These represent the minimum and maximum possible lengths of a duplicate substring.
- Step 2: Perform binary search while `low <= high`. In each iteration, calculate the middle value `mid = low + (high - low) // 2`. This `mid` value represents the length of the substring we are currently searching for.
- Step 3: Implement a `search(mid)` function that checks if a duplicate substring of length `mid` exists. This function uses a rolling hash approach.
- Step 4: Inside `search(mid)`, compute the hash value of the first substring of length `mid`. Store this hash value and its starting index in a hash map.
- Step 5: Iterate through the remaining substrings of length `mid`, updating the hash value using the rolling hash technique. This efficiently calculates the hash value of the next substring based on the previous one.
- Step 6: If a hash value is already present in the hash map, perform an explicit string comparison to confirm the duplicate substring due to potential hash collisions.
- Step 7: If a duplicate substring of length `mid` is found, update `ans_len` to `mid` and `ans_start` to the starting index of the duplicate. Then, set `low = mid + 1` to search for a longer duplicate substring.
- Step 8: If no duplicate substring of length `mid` is found, set `high = mid - 1` to search for a shorter duplicate substring.
- Step 9: After the binary search completes, return the duplicate substring of length `ans_len` starting at index `ans_start`.
Key Insights
- Insight 1: Binary search can be used to efficiently search for the length of the longest duplicate substring. We can check if a duplicate substring of a certain length exists in O(n) time.
- Insight 2: Rolling hash can efficiently compute the hash values of all substrings of a given length. By maintaining a hash table of seen hash values, we can quickly identify potential duplicate substrings.
- Insight 3: A crucial optimization is using a large prime number (ideally 2^64) as the modulus in the rolling hash to minimize the chance of hash collisions. Explicit collision checking is necessary when collisions occur.
Complexity Analysis
Time Complexity: O(NlogN)
Space Complexity: O(N)
Topics
This problem involves: String, Binary Search, Sliding Window, Rolling Hash, Suffix Array, Hash Function.
Companies
Asked at: Coupang.