Open In App

Longest Valid Parentheses Substring

Last Updated : 04 Sep, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

Given a string s consisting of opening and closing parenthesis '(' and ')', find the length of the longest valid parenthesis substring.
A valid parenthesis substring is one where every opening bracket '(' has a corresponding closing bracket ')' in the correct order.

Examples: 

Input: s = "())"
Output: 2
Explanation: The longest valid parentheses substring is "()".

Input: s = "(()())"
Output: 6
Explanation: The entire string "(()())" is a valid parentheses substring of length 6.

[Expected Approach - 1] Using Stack - O(n) Time and O(n) Space

We use a stack to track indices of unmatched '('. By also recording the index of the last unmatched ')', we can calculate the length of each valid substring and keep track of the maximum length found.

Steps below to solve the problem:

  • For every opening parenthesis, we push its index onto the stack.
  • For every closing parenthesis, we pop the stack.
  • If the stack becomes empty after popping, it means we've encountered an unmatched closing parenthesis, so we push the current index to serve as a base for the next potential valid substring.
  • If the stack is not empty, we calculate the length of the valid substring by subtracting the index at the top of the stack from the current index.
  • A variable maxLength keeps track of the maximum length of valid parentheses encountered during the traversal.
C++
#include <iostream>
#include <stack>
using namespace std;

int maxLength(string& s) {
    stack<int> st;

    // Push -1 as the initial index to 
  	// handle the edge case
    st.push(-1);
    int maxLen = 0;
    
    for (int i = 0; i < s.length(); i++) {
        
        // If we encounter an opening parenthesis,
      	// push its index
        if (s[i] == '(') {
            st.push(i);
        } 
        else {
            
            // If we encounter a closing parenthesis,
          	// pop the stack
            st.pop();

            // If stack is empty, push the current index 
            // as a base for the next valid substring
            if (st.empty()) {
                st.push(i);
            } else {
                
                // Update maxLength with the current length 
                // of the valid parentheses substring
                maxLen = max(maxLen, i - st.top());
            }
        }
    }
    return maxLen;
}

int main() {
    string s = "(()())"; 
    cout << maxLength(s) << endl;
    return 0;
}
Java
import java.util.Stack;

class GfG {
    
    static int maxLength(String s) {
        Stack<Integer> st = new Stack<>();

        // Push -1 as the initial index to
      	// handle the edge case
        st.push(-1);
        int maxLen = 0;

        // Traverse the string
        for (int i = 0; i < s.length(); i++) {

            // If we encounter an opening parenthesis, 
          	// push its index
            if (s.charAt(i) == '(') {
                st.push(i);
            } 
            else {

                // If we encounter a closing parenthesis, 
              	// pop the stack
                st.pop();

                // If stack is empty, push the current index 
                // as a base for the next valid substring
                if (st.isEmpty()) {
                    st.push(i);
                } else {

                    // Update maxLength with the current length 
                    // of the valid parentheses substring
                    maxLen = Math.max(maxLen, i - st.peek());
                }
            }
        }

        return maxLen;
    }

    public static void main(String[] args) {
        String s = "(()())";
        System.out.println(maxLength(s));
    }
}
Python
def maxLength(s):
    st = []

    # Push -1 as the initial index to 
    # handle the edge case
    st.append(-1)
    maxLen = 0

    # Traverse the string
    for i in range(len(s)):

        # If we encounter an opening parenthesis,
        # push its index
        if s[i] == '(':
            st.append(i)
        else:

            # If we encounter a closing parenthesis, 
            # pop the stack
            st.pop()

            # If stack is empty, push the current index
            # as a base for the next valid substring
            if not st:
                st.append(i)
            else:
              
                # Update maxLength with the current length 
                # of the valid parentheses substring
                maxLen = max(maxLen, i - st[-1])

    return maxLen

if __name__ == "__main__":
    s = "(()())"
    print(maxLength(s))
C#
using System;
using System.Collections.Generic;

class GfG {
    static int maxLength(string s) {
        Stack<int> st = new Stack<int>();

        // Push -1 as the initial index to handle
      	//   the edge case
        st.Push(-1);
        int maxLen = 0;

        for (int i = 0; i < s.Length; i++) {

            // If we encounter an opening parenthesis, 
          	// push its index
            if (s[i] == '(') {
                st.Push(i);
            } 
            else {

                // If we encounter a closing parenthesis, 
              	// pop the stack
                st.Pop();

                // If stack is empty, push the current index 
                // as a base for the next valid substring
                if (st.Count == 0) {
                    st.Push(i);
                } else {

                    // Update maxLength with the current length 
                    // of the valid parentheses substring
                    maxLen = Math.Max(maxLen, i - st.Peek());
                }
            }
        }

        return maxLen;
    }

    static void Main() {
        string s = "(()())";
        Console.WriteLine(maxLength(s));
    }
}
JavaScript
function maxLength(s) {
    let st = [];

    // Push -1 as the initial index to handle
    // the edge case
    st.push(-1);
    let maxLen = 0;

    // Traverse the string
    for (let i = 0; i < s.length; i++) {
        
        // If we encounter an opening parenthesis, 
        // push its index
        if (s[i] === '(') {
            st.push(i);
        } else {
            
            // If we encounter a closing parenthesis,
            // pop the stack
            st.pop();

            // If stack is empty, push the current index 
            // as a base for the next valid substring
            if (st.length === 0) {
                st.push(i);
            } else {
                
                // Update maxLength with the current length 
                // of the valid parentheses substring
                maxLen = Math.max(maxLen, i - st[st.length - 1]);
            }
        }
    }

    return maxLen;
}

// Driver Code
let s = "(()())";
console.log(maxLength(s));

Output
6

[Expected Approach - 2] Using Dynamic Programming- O(n) Time and O(n) Space

The idea is to solve this problem using dynamic programming (DP) where dp[i] represents the length of the longest valid parentheses substring ending at index i. If a valid substring ends at i, we calculate and store the length of that substring in dp[i].

Steps below to solve the problem:

  • If we encounter an opening parenthesis, we can't form a valid substring yet, so we move to the next character.
  • If we encounter a closing parenthesis, we check the previous character to determine if it forms a valid substring.
    => If the previous character is '(', we have a valid pair, so dp[i] = dp[i-2] + 2 (if i-2 is valid).
    => If the previous character is ')', check if the substring before it forms a valid substring. We use dp[i-1] to determine where the valid substring might start.
  • Also, store the maximum length of valid parentheses during the traversal.
C++
#include <iostream>
#include <vector>
using namespace std;

int maxLength(string& s) {

    int n = s.length();
    vector<int> dp(n, 0);
    int maxLen = 0;

    for (int i = 1; i < n; i++) {
        if (s[i] == ')') {

            // Check if the previous character is an
            // opening parenthesis '('
            if (s[i - 1] == '(') {
                if (i >= 2) {
                    dp[i] = dp[i - 2] + 2;
                }
                else {
                    dp[i] = 2;
                }
            }

            // Check if the previous character is a
            // closing parenthesis ')' and the matching opening
            // parenthesis exists before the valid substring
            else if (i - dp[i - 1] > 0 && s[i - dp[i - 1] - 1] == '(') {
                if (i - dp[i - 1] >= 2) {
                    dp[i] = dp[i - 1] + dp[i - dp[i - 1] - 2] + 2;
                }
                else {
                    dp[i] = dp[i - 1] + 2;
                }
            }

            // Update the maximum length
            maxLen = max(maxLen, dp[i]);
        }
    }

    return maxLen;
}

int main() {
  
    string s = "(()())";
    cout << maxLength(s) << endl;

    return 0;
}
Java
class GfG {
    
    static int maxLength(String s) {

        int n = s.length();
        int[] dp = new int[n];
        int maxLen = 0;
        
        for (int i = 1; i < n; i++) {
            if (s.charAt(i) == ')') {

                // Check if the previous character is an
                // opening parenthesis '('
                if (s.charAt(i - 1) == '(') {
                    if (i >= 2) {
                        dp[i] = dp[i - 2] + 2;
                    }
                    else {
                        dp[i] = 2;
                    }
                }

                // Check if the previous character is a
                // closing parenthesis ')' and the matching
                // opening parenthesis exists before the
                // valid substring
                else if (i - dp[i - 1] > 0 
                        && s.charAt(i - dp[i - 1] - 1) == '(') {
                  
                    if (i - dp[i - 1] >= 2) {
                        dp[i] = dp[i - 1] + dp[i - dp[i - 1] - 2] + 2;
                    }
                    else {
                        dp[i] = dp[i - 1] + 2;
                    }
                }

                // Update the maximum length
                maxLen = Math.max(maxLen, dp[i]);
            }
        }

        return maxLen;
    }

    public static void main(String[] args) {
        String s = "(()())";
        System.out.println(maxLength(s));
    }
}
Python
def maxLength(s):

    n = len(s)
    dp = [0] * n
    maxLen = 0
    
    for i in range(1, n):

        if s[i] == ')':

            # Check if the previous character is an opening
            # parenthesis '('
            if s[i - 1] == '(':
                if i >= 2:
                    dp[i] = dp[i - 2] + 2
                else:
                    dp[i] = 2

            # Check if the previous character is a
            # closing parenthesis ')' and the matching opening
            # parenthesis exists before the valid substring
            elif i - dp[i - 1] > 0 and s[i - dp[i - 1] - 1] == '(':
                if i - dp[i - 1] >= 2:
                    dp[i] = dp[i - 1] + dp[i - dp[i - 1] - 2] + 2
                else:
                    dp[i] = dp[i - 1] + 2

            # Update the maximum length
            maxLen = max(maxLen, dp[i])

    return maxLen


if __name__ == "__main__":

    s = "(()())"
    print(maxLength(s))
C#
using System;

class GfG {
    
    static int maxLength(string s) {

        int n = s.Length;
        int[] dp = new int[n];
        int maxLen = 0;

        for (int i = 1; i < n; i++) {
            
            if (s[i] == ')') {

                // Check if the previous character is an
                // opening parenthesis '('
                if (s[i - 1] == '(') {
                    if (i >= 2) {
                        dp[i] = dp[i - 2] + 2;
                    }
                    else {
                        dp[i] = 2;
                    }
                }

                // Check if the previous character is a
                // closing parenthesis ')' and the matching
                // opening parenthesis exists before the
                // valid substring
                else if (i - dp[i - 1] > 0
                         && s[i - dp[i - 1] - 1] == '(') {
                    if (i - dp[i - 1] >= 2) {
                        dp[i] = dp[i - 1] + dp[i - dp[i - 1] - 2] + 2;
                    }
                    else {
                        dp[i] = dp[i - 1] + 2;
                    }
                }

                // Update the maximum length
                maxLen = Math.Max(maxLen, dp[i]);
            }
        }

        return maxLen;
    }

    static void Main(string[] args) {
        string s = "(()())";
        Console.WriteLine(maxLength(s));
    }
}
JavaScript
function maxLength(s) {
    
    const n = s.length;
    const dp = new Array(n).fill(0);
    let maxLen = 0;

    for (let i = 1; i < n; i++) {
        if (s[i] === ")") {

            // Check if the previous character is an opening
            // parenthesis '('
            if (s[i - 1] === "(") {
                if (i >= 2) {
                    dp[i] = dp[i - 2] + 2;
                }
                else {
                    dp[i] = 2;
                }
            }

            // Check if the previous character is a
            // closing parenthesis ')' and the matching
            // opening parenthesis exists before the valid
            // substring
            else if (i - dp[i - 1] > 0
                     && s[i - dp[i - 1] - 1] === "(") {
                if (i - dp[i - 1] >= 2) {
                    dp[i] = dp[i - 1] + dp[i - dp[i - 1] - 2] + 2;
                }
                else {
                    dp[i] = dp[i - 1] + 2;
                }
            }

            // Update the maximum length
            maxLen = Math.max(maxLen, dp[i]);
        }
    }

    return maxLen;
}

// Driver Code
const s = "(()())";
console.log(maxLength(s));

Output
6

[Expected Approach - 3] Using Two Traversals - O(n) Time and O(1) Space

The idea is to solve the problem using two traversals of the string, one from left to right and one from right to left, while keeping track of the number of open and close parentheses using two counters: open and close.

Steps below to solve the problem:

  • Use two counters: open and close.
  • Traverse once left to right and once right to left.
  • For each character:
    => Increment open if '(', else increment close.
    => If open == close, update max length = 2 * close.
    => If imbalance occurs (close > open in left-to-right, or open > close in right-to-left),
    reset both counters.
  • Two passes ensure both extra ')' and extra '(' cases are handled.
C++
#include <iostream>
using namespace std;

int maxLength(string& s) {
    int maxLen = 0;

    // Left to Right Traversal
    int open = 0, close = 0;
    for (int i=0; i<s.length(); i++) {
        char ch=s[i];
        if (ch == '(') {
            open++;
        }
        else if (ch == ')') {
            close++;
        }

        if (open == close) {
            maxLen = max(maxLen, 2 * close);
        }
        else if (close > open) {
            open = close = 0;
        }
    }

    // Right to Left Traversal
    open = close = 0;
    for (int i = s.size() - 1; i >= 0; i--) {
        if (s[i] == '(') {
            open++;
        }
        else if (s[i] == ')') {
            close++;
        }

        if (open == close) {
            maxLen = max(maxLen, 2 * open);
        }
        else if (open > close) {
            open = close = 0;
        }
    }

    return maxLen;
}

int main() {
    string s = "(()())";
    cout << maxLength(s) << endl;
    return 0;
}
C
#include <stdio.h>
#include <string.h>
#include <stdbool.h>

int maxLength(char s[]) {
    int maxLen = 0;
    
    // Left to Right Traversal
    int open = 0, close = 0;
    int len = strlen(s);
    for (int i = 0; i < len; i++) {
        if (s[i] == '(') {
            open++;
        } else if (s[i] == ')') {
            close++;
        }

        if (open == close) {
            maxLen = (maxLen > 2 * close) ? maxLen : 2 * close;
        } else if (close > open) {
            open = close = 0;
        }
    }

    // Right to Left Traversal
    open = close = 0;
    for (int i = len - 1; i >= 0; i--) {
        if (s[i] == '(') {
            open++;
        } else if (s[i] == ')') {
            close++;
        }

        if (open == close) {
            maxLen = (maxLen > 2 * open) ? maxLen : 2 * open;
        } else if (open > close) {
            open = close = 0;
        }
    }

    return maxLen;
}

int main() {
    char s[] = "(()())";
    printf("%d\n", maxLength(s));
    return 0;
}
Java
class GfG {
    static int maxLength(String s) {
        int maxLen = 0;
        
        // Left to Right Traversal
        int open = 0, close = 0;
        for (int i=0; i<s.length(); i++) {
            char ch=s.charAt(i);
            if (ch == '(') {
                open++;
            } else if (ch == ')') {
                close++;
            }

            if (open == close) {
                maxLen = Math.max(maxLen, 2 * close);
            } else if (close > open) {
                open = close = 0;
            }
        }

        // Right to Left Traversal
        open = close = 0;
        for (int i = s.length() - 1; i >= 0; i--) {
            if (s.charAt(i) == '(') {
                open++;
            } else if (s.charAt(i) == ')') {
                close++;
            }

            if (open == close) {
                maxLen = Math.max(maxLen, 2 * open);
            } else if (open > close) {
                open = close = 0;
            }
        }

        return maxLen;
    }

    public static void main(String[] args) {
        String s = "(()())";
        System.out.println(maxLength(s));
    }
}
Python
def maxLength(s):
    maxLen = 0
    n = len(s)
    
    # Left to Right Traversal
    open = close = 0
    for i in range(n):
        ch = s[i]
        if ch == '(':
            open += 1
        elif ch == ')':
            close += 1
        
        if open == close:
            maxLen = max(maxLen, 2 * close)
        elif close > open:
            open = close = 0
    
    # Right to Left Traversal
    open = close = 0
    for i in range(n - 1, -1, -1):
        ch = s[i]
        if ch == '(':
            open += 1
        elif ch == ')':
            close += 1
        
        if open == close:
            maxLen = max(maxLen, 2 * open)
        elif open > close:
            open = close = 0
    
    return maxLen

if __name__ == "__main__":
    s = "(()())"
    print(maxLength(s))
C#
using System;

class GfG {
    static int maxLength(string s) {
        int maxLen = 0;
        
        // Left to Right Traversal
        int n=s.Length;
        int open = 0, close = 0;
        for (int i = 0; i < n; i++) {
            char ch = s[i];
            if (ch == '(') {
                open++;
            } else if (ch == ')') {
                close++;
            }

            if (open == close) {
                maxLen = Math.Max(maxLen, 2 * close);
            } else if (close > open) {
                open = close = 0;
            }
        }

        // Right to Left Traversal
        open = close = 0;
        for (int i = s.Length - 1; i >= 0; i--) {
            if (s[i] == '(') {
                open++;
            } else if (s[i] == ')') {
                close++;
            }

            if (open == close) {
                maxLen = Math.Max(maxLen, 2 * open);
            } else if (open > close) {
                open = close = 0;
            }
        }

        return maxLen;
    }

    static void Main(string[] args) {
        string s = "(()())";
        Console.WriteLine(maxLength(s));
    }
}
JavaScript
function maxLength(s) {
    let maxLen = 0;
    
    // Left to Right Traversal
    let open = 0, close = 0;
    for (let i = 0; i < s.length; i++) {
        if (s[i] === '(') {
            open++;
        } else if (s[i] === ')') {
            close++;
        }

        if (open === close) {
            maxLen = Math.max(maxLen, 2 * close);
        } else if (close > open) {
            open = close = 0;
        }
    }

    // Right to Left Traversal
    open = close = 0;
    for (let i = s.length - 1; i >= 0; i--) {
        if (s[i] === '(') {
            open++;
        } else if (s[i] === ')') {
            close++;
        }

        if (open === close) {
            maxLen = Math.max(maxLen, 2 * open);
        } else if (open > close) {
            open = close = 0;
        }
    }

    return maxLen;
}

// Driver Code
const s = "(()())";
console.log(maxLength(s));

Output
6

Length of the longest valid substring

Explore