Length of the longest valid substring

Given a string consisting of opening and closing parenthesis, find length of the longest valid parenthesis substring.

Examples:

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.

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program to find length of the longest valid
// substring
#include<bits/stdc++.h>
using namespace std;
  
int findMaxLen(string str)
{
    int n = str.length();
  
    // Create a stack and push -1 as initial index to it.
    stack<int> stk;
    stk.push(-1);
  
    // Initialize result
    int result = 0;
  
    // Traverse all characters of given string
    for (int i=0; i<n; i++)
    {
        // If opening bracket, push index of it
        if (str[i] == '(')
          stk.push(i);
  
        else // If closing bracket, i.e.,str[i] = ')'
        {
            // Pop the previous opening bracket's index
            stk.pop();
  
            // Check if this length formed with base of
            // current valid substring is more than max 
            // so far
            if (!stk.empty())
                result = max(result, i - stk.top());
  
            // If stack is empty. push current index as 
            // base for next valid substring (if any)
            else stk.push(i);
        }
    }
  
    return result;
}
  
// Driver program
int main()
{
    string str = "((()()";
    cout << findMaxLen(str) << endl;
  
    str = "()(()))))";
    cout << findMaxLen(str) << endl ;
  
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program to find length of the longest valid
// substring
  
import java.util.Stack;
      
class Test
{
    // method to get length of the longest valid
    static int findMaxLen(String str)
    {
        int n = str.length();
       
        // Create a stack and push -1 as initial index to it.
        Stack<Integer> stk = new Stack<>();
        stk.push(-1);
       
        // Initialize result
        int result = 0;
       
        // Traverse all characters of given string
        for (int i=0; i<n; i++)
        {
            // If opening bracket, push index of it
            if (str.charAt(i) == '(')
              stk.push(i);
       
            else // If closing bracket, i.e.,str[i] = ')'
            {
                // Pop the previous opening bracket's index
                stk.pop();
       
                // Check if this length formed with base of
                // current valid substring is more than max 
                // so far
                if (!stk.empty())
                    result = Math.max(result, i - stk.peek());
       
                // If stack is empty. push current index as 
                // base for next valid substring (if any)
                else stk.push(i);
            }
        }
       
        return result;
    }
      
    // Driver method
    public static void main(String[] args) 
    {
        String str = "((()()";
        System.out.println(findMaxLen(str));
       
        str = "()(()))))";
        System.out.println(findMaxLen(str));
       
    }
}

chevron_right


Python

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python program to find length of the longest valid
# substring
  
def findMaxLen(string):
    n = len(string)
  
    # Create a stack and push -1 as initial index to it.
    stk = []
    stk.append(-1)
  
    # Initialize result
    result = 0
  
    # Traverse all characters of given string
    for i in xrange(n):
      
        # If opening bracket, push index of it
        if string[i] == '(':
            stk.append(i)
  
        else:    # If closing bracket, i.e., str[i] = ')'
      
            # Pop the previous opening bracket's index
            stk.pop()
      
            # Check if this length formed with base of
            # current valid substring is more than max 
            # so far
            if len(stk) != 0:
                result = max(result, i - stk[len(stk)-1])
  
            # If stack is empty. push current index as 
            # base for next valid substring (if any)
            else:
                stk.append(i)
  
    return result
  
# Driver program
string = "((()()"
print findMaxLen(string)
  
string = "()(()))))"
print findMaxLen(string)
  
# This code is contributed by Bhavya Jain

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# program to find length of 
// the longest valid substring
using System;
using System.Collections.Generic;
  
class GFG
{
// method to get length of 
// the longest valid 
public static int findMaxLen(string str)
{
    int n = str.Length;
  
    // Create a stack and push -1 as 
    // initial index to it. 
    Stack<int> stk = new Stack<int>();
    stk.Push(-1);
  
    // Initialize result 
    int result = 0;
  
    // Traverse all characters of
    // given string 
    for (int i = 0; i < n; i++)
    {
        // If opening bracket, push 
        // index of it 
        if (str[i] == '(')
        {
            stk.Push(i);
        }
  
        else // If closing bracket, 
             // i.e.,str[i] = ')'
        {
            // Pop the previous opening 
            // bracket's index 
            stk.Pop();
  
            // Check if this length formed 
            // with base of current valid 
            // substring is more than max 
            // so far 
            if (stk.Count > 0)
            {
                result = Math.Max(result, i - stk.Peek());
            }
  
            // If stack is empty. push current
            // index as base for next valid 
            // substring (if any) 
            else
            {
                stk.Push(i);
            }
        }
    }
  
    return result;
}
  
// Driver Code 
public static void Main(string[] args)
{
    string str = "((()()";
    Console.WriteLine(findMaxLen(str));
  
    str = "()(()))))";
    Console.WriteLine(findMaxLen(str));
}
}
  
// This code is contributed by Shrikant13

chevron_right



Output:

4
6

Explanation with example:

Input: str = "(()()"

Initialize result as 0 and stack with one item -1.

For i = 0, str[0] = '(', we push 0 in stack

For i = 1, str[1] = '(', we push 1 in stack

For i = 2, str[2] = ')', 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[3] = '(', we push again, stack is [-1, 0, 3].

For i = 4, str[4] = ')', 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.

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program to find length of the longest valid
// substring
#include<bits/stdc++.h>
using namespace std;
  
int findMaxLen(string s)
{
    if (s.length() <= 1) return 0;
      
    //Initialize curMax to zero
    int curMax = 0;
  
    vector<int> longest(s.size(), 0);
  
    //Iterate over the string starting from second index
    for (int i = 1; i < s.length(); i++) {
        if (s[i] == ')' && i - longest[i - 1] - 1 >= 0 &&
            s[i - longest[i - 1] - 1] == '(') {
                longest[i] = longest[i - 1] + 2 + 
                ((i - longest[i - 1] - 2 >= 0) 
                ? longest[i - longest[i - 1] - 2] : 0);
                    curMax = max(longest[i], curMax);
        }
    }
    return curMax;
}
  
// Driver program
int main()
{
    string str = "((()()";
    cout << findMaxLen(str) << endl;
  
    str = "()(()))))";
    cout << findMaxLen(str) << endl ;
  
    return 0;
}
// This code is contributed by Vipul Lohani

chevron_right



Output:

4
6

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.



My Personal Notes arrow_drop_up

Improved By : Vipul Lohani, shrikanth13