Given a string containing just the characters '('
and ')'
, find the length of the longest valid (well-formed) parentheses substring.
For "(()"
, the longest valid parentheses substring is "()"
, which has length = 2.
Another example is ")()())"
, where the longest valid parentheses substring is "()()"
, which has length = 4.
We need to determine the length of the largest valid substring of parentheses from a given string.
\nAlgorithm
\nIn this approach, we consider every possible non-empty even length substring from the given string and check whether it\'s\na valid string of parentheses or not. In order to check the validity, we use the Stack\'s Method.
\nEvery time we\nencounter a , we push it onto the stack. For every encountered, we pop a from the stack. If isn\'t\n available on the stack for popping at anytime or if stack contains some elements after processing complete substring, the substring of parentheses is invalid. In this way, we repeat the\n process for every possible substring and we keep on\n storing the length of the longest valid string found so far.
\nExample:\n"((())"\n\n(( --> invalid\n(( --> invalid\n() --> valid, length=2\n)) --> invalid\n((()--> invalid\n(())--> valid, length=4\nmaxlength=4\n
Complexity Analysis
\nTime complexity : . Generating every possible substring from a string of length requires . Checking validity of a string of length requires .
\nSpace complexity : . A stack of depth will be required for the longest substring.
\nAlgorithm
\nThis problem can be solved by using Dynamic Programming. We make use of a array where th element of represents the length of the longest valid substring ending at th index. We initialize the complete array with 0\'s. Now, it\'s obvious that the valid substrings must end with . This further leads to the conclusion that the substrings ending with will always contain \'0\' at their corresponding indices. Thus, we update the array only when is encountered.
\nTo fill array we will check every two consecutive characters of the string and if
\n\n and , i.e. string looks like \n
\n\n\n
\nWe do so because the ending "()" portion is a valid substring anyhow and leads to an increment of 2 in the length of the just previous valid substring\'s length.
\n\n and , i.e. string looks like \n
\nif then
\n\n\n
\nThe reason behind this is that if the 2nd last was a part of a valid substring (say ), for the last to be a part of a larger substring, there must be a corresponding starting which lies before the valid substring of which the 2nd last is a part (i.e. before ). Thus, if the character before happens to be , we update the as an addition of in the length of which is . To this, we also add the length of the valid substring just before the term "(,sub_s,)" , i.e. .
\nFor better understanding of this method, see this example:
\n\n!?!../Documents/32_Longest_Valid2.json:1000,563!?!
\n\nComplexity Analysis
\nTime complexity : . Single traversal of string to fill dp array is done.
\nSpace complexity : . dp array of size is used.
\nAlgorithm
\nInstead of finding every possible string and checking its validity, we can make use of stack while scanning\nthe given string to check if the string scanned so far is valid, and also the length of the longest valid string. In order to do so, we start by pushing onto the stack.
\nFor every encountered, we push its index onto the stack.
\nFor every encountered, we pop the topmost element and subtract the current element\'s index from the top element of the stack, which gives the length of the currently encountered valid string of parentheses. If while popping the element, the stack becomes empty, we push the current element\'s index onto the stack. In this way, we keep on calculating the lengths of the valid substrings, and return the length of the longest valid string at the end.
\nSee this example for better understanding.
\n\n!?!../Documents/32_Longest_Valid_stack_new.json:1000,563!?!
\n\nComplexity Analysis
\nTime complexity : . is the length of the given string..
\nSpace complexity : . The size of stack can go up to .
\nAlgorithm
\nIn this approach, we make use of two counters and . First, we start traversing the string from the left towards the right and for every encountered, we increment the counter and for every encountered, we increment the counter. Whenever becomes equal to , we calculate the length of the current valid string and keep track of maximum length substring found so far. If becomes greater than we reset and to .
\nNext, we start traversing the string from right to left and similar procedure is applied.
\nExample of this approach:
\n\n!?!../Documents/32_Longest_Validlr.json:1000,563!?!
\n\nComplexity Analysis
\nTime complexity : . Two traversals of the string.
\nSpace complexity : . Only two extra variables and are needed.
\nAnalysis written by: @vinod23
\n