Range Queries for Longest Correct Bracket Subsequence Set | 2
Last Updated :
30 Apr, 2024
Given a bracket sequence or in other words a string S of length n, consisting of characters ‘(‘ and ‘)’. Find the length of the maximum correct bracket subsequence of sequence for a given query range. Note: A correct bracket sequence is the one that has matched bracket pairs or which contains another nested correct bracket sequence. For e.g (), (()), ()() are some correct bracket sequence.
Examples:
Input : S = ())(())(())(
Start Index of Range = 0,
End Index of Range = 11
Output : 10
Explanation: Longest Correct Bracket Subsequence is ()(())(())
Input : S = ())(())(())(
Start Index of Range = 1,
End Index of Range = 2
Output : 0
Approach: In the Previous post (SET 1) we discussed a solution that works in O(long) for each query, now is this post we will go to see a solution that works in O(1) for each query.
The idea is based on the Post length of the longest valid balanced substring If we marked indexes of all Balanced parentheses/brackets in a temporary array (here we named it BCP[], BOP[] ) then we answer each query in O(1) time.
Algorithm :
stack is used to get the index of balance bracket.
Traverse a string from 0 ..to n
IF we seen a closing bracket,
( i.e., str[i] = ')' && stack is not empty )
Then mark both "open & close" bracket indexes as 1.
BCP[i] = 1;
BOP[stk.top()] = 1;
And At last, stored cumulative sum of BCP[] & BOP[]
Run a loop from 1 to n
BOP[i] +=BOP[i-1], BCP[i] +=BCP[i-1]
Now you can answer each query in O(1) time
(BCP[e] - BOP[s-1]])*2;
Below is the implementation of the above idea.
C++
#include <bits/stdc++.h>
using namespace std;
void constructBalanceArray(int BOP[], int BCP[], const char* str, int n) {
stack<int> stk;
fill(BOP, BOP + n + 1, 0);
fill(BCP, BCP + n + 1, 0);
for (int i = 0; i < n; i++) {
if (str[i] == '(') {
stk.push(i);
} else { // It's a ')'
if (!stk.empty()) {
int openIndex = stk.top();
stk.pop();
BOP[openIndex] = 1; // There's a valid '(' at openIndex
BCP[i] = 1; // There's a valid ')' at i
}
}
}
// Convert the BOP and BCP into prefix sums
for (int i = 1; i <= n; i++) {
BOP[i] += BOP[i - 1];
BCP[i] += BCP[i - 1];
}
}
int query(int BOP[], int BCP[], int s, int e) {
if (s == 0) {
return (BCP[e] - BOP[s]) * 2;
} else {
return (BCP[e] - BCP[s - 1] - (BOP[s] - BOP[s - 1])) * 2;
}
}
int main() {
const char str[] = "())(())(())(";
int n = strlen(str);
int BCP[n + 1], BOP[n + 1];
constructBalanceArray(BOP, BCP, str, n);
vector<pair<int, int>> queries = {{4, 11}, {3, 4}, {0, 2}, {0, 4}, {1, 2}};
for (const auto& query_pair : queries) {
int start = query_pair.first;
int end = query_pair.second;
cout << "Maximum Length Correct Bracket Subsequence between " << start + 1 << " and " << end + 1 << " = " << query(BOP, BCP, start, end) << endl;
}
return 0;
}
Java
import java.util.*;
class GFG {
static void constructBalanceArray(int[] BOP, int[] BCP, String str, int n) {
Stack<Integer> stk = new Stack<>();
Arrays.fill(BOP, 0);
Arrays.fill(BCP, 0);
for (int i = 0; i < n; i++) {
if (str.charAt(i) == '(') {
stk.push(i);
} else { // It's a ')'
if (!stk.isEmpty()) {
int openIndex = stk.pop();
BOP[openIndex] = 1; // Mark this '(' as balanced
BCP[i] = 1; // Mark this ')' as balanced
}
}
}
// Convert to prefix sums
for (int i = 1; i < n; i++) {
BOP[i] += BOP[i - 1];
BCP[i] += BCP[i - 1];
}
}
static int query(int[] BOP, int[] BCP, int s, int e) {
if (s > 0 && BOP[s - 1] == BOP[s]) {
return (BCP[e] - BOP[s]) * 2;
} else {
return (BCP[e] - (s > 0 ? BOP[s - 1] : 0)) * 2;
}
}
public static void main(String[] args) {
String str = "())(())(())(";
int n = str.length();
int[] BCP = new int[n];
int[] BOP = new int[n];
constructBalanceArray(BOP, BCP, str, n);
// Define the queries
int[][] queries = {
{5, 11}, // indices are 0-based, add 1 if 1-based is needed
{4, 5},
{1, 5},
{0, 2}
};
for (int[] query : queries) {
int startIndex = query[0];
int endIndex = query[1];
System.out.println("Maximum Length Correct Bracket Subsequence between " +
(startIndex + 1) + " and " + (endIndex + 1) +
" = " + query(BOP, BCP, startIndex, endIndex));
}
}
}
Python3
def constructBalanceArray(BOP, BCP, s, n):
stk = [] # No need to push -1 as mentioned in the comment; we never use that
for i in range(n):
if s[i] == '(':
stk.append(i)
else:
if stk:
open_index = stk.pop()
BOP[open_index] = 1
BCP[i] = 1
# No else needed here; the initial values are zero
# Convert to prefix sums
for i in range(1, n):
BOP[i] += BOP[i - 1]
BCP[i] += BCP[i - 1]
def query(BOP, BCP, s, e):
s_adjusted = s - 1 # Adjusting for 0-based index access
e_adjusted = e
if s_adjusted > 0 and BOP[s_adjusted - 1] == BOP[s_adjusted]:
return (BCP[e_adjusted] - BOP[s_adjusted]) * 2
else:
return (BCP[e_adjusted] - (BOP[s_adjusted - 1] if s_adjusted > 0 else 0)) * 2
if __name__ == '__main__':
string = "())(())(())("
n = len(string)
BCP = [0] * n
BOP = [0] * n
constructBalanceArray(BOP, BCP, string, n)
queries = [(5, 11), (4, 5), (1, 5)]
for start, end in queries:
max_length = query(BOP, BCP, start, end)
print(f"Maximum Length of Balanced Bracket Subsequence from {start} to {end} = {max_length}")
C#
using System;
using System.Collections.Generic;
class GFG
{
// Function for precomputation
static void constructBalanceArray(int[] BOP, int[] BCP, string str, int n)
{
Stack<int> stk = new Stack<int>();
for (int i = 0; i < n; i++)
{
if (str[i] == '(')
{
stk.Push(i);
}
else
{
if (stk.Count > 0)
{
int matchedOpenIndex = stk.Pop();
BOP[matchedOpenIndex] = 1;
BCP[i] = 1;
}
}
}
// Building prefix sums
for (int i = 1; i < n; i++)
{
BOP[i] += BOP[i - 1];
BCP[i] += BCP[i - 1];
}
}
// Function to return output of each query in O(1)
static int query(int[] BOP, int[] BCP, int s, int e)
{
if (s > 1 && BOP[s - 2] == BOP[s - 1])
{
return (BCP[e] - BOP[s - 1]) * 2;
}
else
{
return (BCP[e] - (s > 1 ? BOP[s - 2] : 0)) * 2;
}
}
// Driver code
public static void Main()
{
string str = "())(())(())(";
int n = str.Length;
int[] BCP = new int[n + 1];
int[] BOP = new int[n + 1];
constructBalanceArray(BOP, BCP, str, n);
// Test cases
var queries = new[] { (5, 11), (4, 5), (1, 5) };
foreach (var (startIndex, endIndex) in queries)
{
int maxLen = query(BOP, BCP, startIndex, endIndex);
Console.WriteLine($"Maximum Length Correct Bracket Subsequence between {startIndex} and {endIndex} = {maxLen}");
}
}
}
Javascript
<script>
// Function for precomputation
function constructBalanceArray(BOP, BCP, str, n) {
var stk = [];
for (var i = 0; i < n; i++) {
if (str[i] === '(')
stk.push(i);
else {
if (stk.length !== 0) {
BCP[i] = 1;
BOP[stk[stk.length - 1]] = 1;
stk.pop();
} else
BCP[i] = 0;
}
}
for (var i = 1; i < n; i++) {
BCP[i] += BCP[i - 1];
BOP[i] += BOP[i - 1];
}
}
// Function to return output of each query in O(1)
function query(BOP, BCP, s, e) {
if (BOP[s - 1] === BOP[s]) {
return (BCP[e] - BOP[s]) * 2;
} else {
return (BCP[e] - BOP[s] + 1) * 2;
}
}
// Driver program to test above function
var str = "())(())(())(";
var n = str.length;
var BCP = Array(n + 1).fill(0);
var BOP = Array(n + 1).fill(0);
constructBalanceArray(BOP, BCP, str, n);
var startIndex = 5, endIndex = 11;
document.write("Maximum Length of Correct Bracket Subsequence between " +
startIndex + " and " + endIndex + " = " +
query(BOP, BCP, startIndex, endIndex) + "<br>");
startIndex = 4, endIndex = 5;
document.write("Maximum Length of Correct Bracket Subsequence between " +
startIndex + " and " + endIndex + " = " +
query(BOP, BCP, startIndex, endIndex) + "<br>");
startIndex = 1, endIndex = 5;
document.write("Maximum Length of Correct Bracket Subsequence between " +
startIndex + " and " + endIndex + " = " +
query(BOP, BCP, startIndex, endIndex) + "<br>");
</script>
OutputMaximum Length Correct Bracket Subsequence between 5 and 11 = 4
Maximum Length Correct Bracket Subsequence between 4 and 5 = 0
Maximum Length Correct Bracket Subsequence between 1 and 5 = 2
The time complexity for each query is O(1).
Overall time Complexity: O(n)
Auxiliary Space: O(n)
Please Login to comment...