You are given a 0-indexed string s
, a string a
, a string b
, and an integer k
.
An index i
is beautiful if:
0 <= i <= s.length - a.length
s[i..(i + a.length - 1)] == a
j
such that:
0 <= j <= s.length - b.length
s[j..(j + b.length - 1)] == b
|j - i| <= k
Return the array that contains beautiful indices in sorted order from smallest to largest.
Example 1:
Input: s = "isawsquirrelnearmysquirrelhouseohmy", a = "my", b = "squirrel", k = 15 Output: [16,33] Explanation: There are 2 beautiful indices: [16,33]. - The index 16 is beautiful as s[16..17] == "my" and there exists an index 4 with s[4..11] == "squirrel" and |16 - 4| <= 15. - The index 33 is beautiful as s[33..34] == "my" and there exists an index 18 with s[18..25] == "squirrel" and |33 - 18| <= 15. Thus we return [16,33] as the result.
Example 2:
Input: s = "abcd", a = "a", b = "a", k = 4 Output: [0] Explanation: There is 1 beautiful index: [0]. - The index 0 is beautiful as s[0..0] == "a" and there exists an index 0 with s[0..0] == "a" and |0 - 0| <= 4. Thus we return [0] as the result.
Constraints:
1 <= k <= s.length <= 5 * 105
1 <= a.length, b.length <= 5 * 105
s
, a
, and b
contain only lowercase English letters.When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force approach to finding beautiful indices is to check every possible index to see if it meets the beautiful criteria. We will go through all potential starting points and exhaustively check all other indices to determine which ones are 'beautiful'.
Here's how the algorithm would work step-by-step:
def find_beautiful_indices_brute_force(text, pattern1, pattern2, distance):
beautiful_indices = []
for first_pattern_start in range(len(text)):
# Check if pattern1 exists starting at this index
if text[first_pattern_start:first_pattern_start + len(pattern1)] == pattern1:
for second_pattern_start in range(len(text)):
# Find all occurrences of pattern2 in the text
if text[second_pattern_start:second_pattern_start + len(pattern2)] == pattern2:
# Check if pattern2 is within the distance from pattern1
if abs(first_pattern_start - second_pattern_start) <= distance:
# Mark the index as beautiful if the condition is met
beautiful_indices.append(first_pattern_start)
break # avoid duplicates
return sorted(list(set(beautiful_indices)))
The efficient method avoids redundant checks by leveraging string matching algorithms. It first locates all occurrences of the search strings within the large text, then identifies 'beautiful' positions based on distance criteria between the located occurrences. This prevents repeatedly scanning the entire large text.
Here's how the algorithm would work step-by-step:
def find_beautiful_indices(string, search_word1, search_word2, maximum_distance): beautiful_indices = [] search_word1_indices = [] search_word2_indices = [] # Find all occurrences of search_word1 in string for index in range(len(string) - len(search_word1) + 1): if string[index:index + len(search_word1)] == search_word1: search_word1_indices.append(index) # Find all occurrences of search_word2 in string for index in range(len(string) - len(search_word2) + 1): if string[index:index + len(search_word2)] == search_word2: search_word2_indices.append(index) # Iterate through each index of search_word1 for search_word1_index in search_word1_indices: # Check if a search_word2 index is within maximum_distance for search_word2_index in search_word2_indices:
if abs(search_word1_index - search_word2_index) <= maximum_distance: # Mark index as beautiful if condition is met beautiful_indices.append(search_word1_index) break
# Removing duplicates while preserving order beautiful_indices = sorted(list(set(beautiful_indices))) return beautiful_indices
Case | How to Handle |
---|---|
Empty s or p string | Return an empty list if either s or p is empty, as no valid indices can exist. |
s and p are identical strings | Return a list containing only the index 0 since 'p' will be found at the very start of 's'. |
p is longer than s | Return an empty list, as 'p' cannot be a substring of 's' if it's longer. |
s and p contain only one repeating character | The solution should efficiently find all occurrences; the KMP algorithm handles repeating character patterns correctly. |
s contains many overlapping occurrences of p | The solution must iterate and check for each overlapping occurence to correctly identify all indices. |
Very long s and relatively short p, approaching maximum string length | Ensure the algorithm's time complexity is considered and optimizes the search for performance. |
s contains Unicode characters | The KMP algorithm should work correctly as it compares code points and not rely on ASCII assumption. |
s and p are extremely long strings, potentially causing memory issues | Consider a rolling hash or similar technique to avoid storing the entire string in memory at once. |