You are given a string word
and an array of strings forbidden
.
A string is called valid if none of its substrings are present in forbidden
.
Return the length of the longest valid substring of the string word
.
A substring is a contiguous sequence of characters in a string, possibly empty.
Example 1:
Input: word = "cbaaaabc", forbidden = ["aaa","cb"]
Output: 4
Explanation: There are 11 valid substrings in word: "c", "b", "a", "ba", "aa", "bc", "baa", "aab", "ab", "abc" and "aabc". The length of the longest valid substring is 4.
It can be shown that all other substrings contain either "aaa" or "cb" as a substring.
Example 2:
Input: word = "leetcode", forbidden = ["de","le","e"]
Output: 4
Explanation: There are 11 valid substrings in word: "l", "t", "c", "o", "d", "tc", "co", "od", "tco", "cod", and "tcod". The length of the longest valid substring is 4.
It can be shown that all other substrings contain either "de", "le", or "e" as a substring.
Constraints:
1 <= word.length <= 10^5
word
consists only of lowercase English letters.1 <= forbidden.length <= 10^5
1 <= forbidden[i].length <= 10
forbidden[i]
consists only of 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 method for this problem is like trying every single possible piece of the string to see if it's valid. We check each piece to see if the parentheses are correctly matched, throwing out invalid pieces and remembering the longest valid one we've found so far. It's an exhaustive approach.
Here's how the algorithm would work step-by-step:
def longest_valid_substring_brute_force(input_string):
max_length = 0
for start_index in range(len(input_string)):
for end_index in range(start_index + 1, len(input_string) + 1):
substring = input_string[start_index:end_index]
# Check if substring is valid. Prevents unnecessary length checks.
if is_valid_parentheses(substring):
substring_length = len(substring)
# Update max_length if current substring is longer
if substring_length > max_length:
max_length = substring_length
return max_length
def is_valid_parentheses(substring):
stack = []
for char in substring:
if char == '(':
stack.append(char)
elif char == ')':
# Check for mismatched parenthesis and invalid substrings
if not stack:
return False
stack.pop()
# Valid only if stack is empty, meaning all parens are matched
return not stack
The most efficient way to find the longest valid substring involves tracking the balance of opening and closing parentheses. We can utilize this balance to detect and correct imbalances, marking potential start and end points of valid substrings. This approach avoids unnecessary checks by focusing on the core property of balanced parentheses.
Here's how the algorithm would work step-by-step:
def longest_valid_parentheses(input_string):
max_length = 0
open_parentheses_count = 0
start_index = 0
for index in range(len(input_string)):
if input_string[index] == '(':
open_parentheses_count += 1
else:
open_parentheses_count -= 1
if open_parentheses_count < 0:
# Reset when closing parens exceed opening ones.
start_index = index + 1
open_parentheses_count = 0
elif open_parentheses_count == 0:
max_length = max(max_length, index - start_index + 1)
else:
max_length = max(max_length, index - start_index + 1)
close_parentheses_count = 0
end_index = len(input_string) - 1
for index in range(len(input_string) - 1, -1, -1):
if input_string[index] == ')':
close_parentheses_count += 1
else:
close_parentheses_count -= 1
if close_parentheses_count < 0:
# Reset when opening parens exceed closing ones.
end_index = index - 1
close_parentheses_count = 0
elif close_parentheses_count == 0:
max_length = max(max_length, end_index - index + 1)
else:
max_length = max(max_length, end_index - index + 1)
return max_length
Case | How to Handle |
---|---|
Null or empty string input | Return 0 as there are no valid substrings. |
Input string of length 1 | Return 0 because a valid substring requires at least two characters. |
String with only opening parentheses | Return 0 as there are no closing parentheses to form a valid substring. |
String with only closing parentheses | Return 0 as there are no opening parentheses to form a valid substring. |
Maximum string length exceeding available memory | The stack-based approach efficiently handles large inputs under memory constraints, assuming reasonable system limits. |
Nested valid substrings e.g. '(()())' | Stack approach naturally handles nested valid substrings correctly. |
Unbalanced parenthesis at the beginning of the string | Stack approach tracks the base and corrects the length. |
String with characters other than '(' and ')' | The algorithm only considers '(' and ')', effectively ignoring other characters. |