Longest Valid Parentheses Substring
Last Updated :
04 Sep, 2025
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));
[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));
[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));
Length of the longest valid substring
Explore
DSA Fundamentals
Data Structures
Algorithms
Advanced
Interview Preparation
Practice Problem