Given a string consisting of opening and closing parenthesis, find length of the longest valid parenthesis substring.
Input : ((() Output : 2 Explanation : () Input: )()()) Output : 4 Explanation: ()() Input: ()(())))) Output: 6 Explanation: ()(())
A Simple Approach is to find all the substrings of given string. For every string, check if it is a valid string or not. If valid and length is more than maximum length so far, then update maximum length. We can check whether a substring is valid or not in linear time using a stack (See this for details). Time complexity of this solution is O(n2.
An Efficient Solution can solve this problem in O(n) time. The idea is to store indexes of previous starting brackets in a stack. The first element of stack is a special element that provides index before beginning of valid substring (base for next valid string).
1) Create an empty stack and push -1 to it. The first element of stack is used to provide base for next valid string. 2) Initialize result as 0. 3) If the character is '(' i.e. str[i] == '('), push index 'i' to the stack. 2) Else (if the character is ')') a) Pop an item from stack (Most of the time an opening bracket) b) If stack is not empty, then find length of current valid substring by taking difference between current index and top of the stack. If current length is more than result, then update the result. c) If stack is empty, push current index as base for next valid substring. 3) Return result.
Below is the implementations of above algorithm.
Explanation with example:
Input: str = "(()()" Initialize result as 0 and stack with one item -1. For i = 0, str = '(', we push 0 in stack For i = 1, str = '(', we push 1 in stack For i = 2, str = ')', currently stack has [-1, 0, 1], we pop from the stack and the stack now is [-1, 0] and length of current valid substring becomes 2 (we get this 2 by subtracting stack top from current index). Since current length is more than current result, we update result. For i = 3, str = '(', we push again, stack is [-1, 0, 3]. For i = 4, str = ')', we pop from the stack, stack becomes [-1, 0] and length of current valid substring becomes 4 (we get this 4 by subtracting stack top from current index). Since current length is more than current result, we update result.
Another Efficient Approach can solve the problem in O(n) time. The idea is to maintain an array which stores the length of longest valid substring ending at that index. We iterate through the array and return the maximum value.
1) Create an array longest of length n (size of the input string) initialized to zero. The array will store the length of the longest valid substring ending at that index. 2) Initialize result as 0. 3) Iterate through the string from second character a) If the character is '(' set longest[i]=0 as no valid sub-string will end with '('. b) Else i) if s[i-1] = '(' set longest[i] = longest[i-2] + 2 ii) else set longest[i] = longest[i-1] + 2 + longest[i-longest[i-1]-2] 4) In each iteration update result as the maximum of result and longest[i] 5) Return result.
Below is the C++ implementations of above algorithm.
Thanks to Gaurav Ahirwar and Ekta Goel for suggesting above approach.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.
- Longest Even Length Substring such that Sum of First and Second Half is same
- Length of the longest substring with equal 1s and 0s
- Length of the longest substring without repeating characters
- Find length of longest subsequence of one string which is substring of another string
- Longest substring with count of 1s more than 0s
- Longest Common Substring | DP-29
- Longest Palindromic Substring | Set 1
- Longest Non-palindromic substring
- Longest Palindromic Substring | Set 2
- Longest substring of vowels
- Maximum length substring having all same characters after k changes
- Longest substring having K distinct vowels
- Longest repeating and non-overlapping substring
- Print the longest common substring
- Substring with highest frequency length product