Range Queries for Longest Correct Bracket Subsequence Set | 2
Given a string s of length n, consisting of opening and closing brackets and an array queries[] consisting of q queries of type [start, end], where start defines the starting point and end defines the ending point. For each query, the task is to find the maximum length of the valid bracket subsequence from index start to end.
Note: A correct bracket sequence has matched bracket pairs or contains another nested correct bracket sequence.
Examples:
Input: s = "())(())(())(", start = 0, end = 11
Output: 10
Explanation: Longest Correct Bracket Subsequence is ()(())(())Input : s = "())(())(())(", start = 1, end = 2
Output : 0
Note: An approach using Segment Tree has been discussed in article Range Query Set 1 that works in O(log n) for each query.
Approach:
The idea is to pre-compute the valid bracket subsequences for each index of string s. To do so, create two arrays open[] and close[], each of size n, where open[] marks the valid open bracket and close[] marks the valid closing bracket. Also, create a stack to store the indices of opening brackets. Start from the 0th index, if the character is '(' store the index in stack, else check if stack is not empty i.e. at least one opening bracket is yet unmatched, if so, remove the index from stack, and mark both open[] and close[] arrays. At last, transform these two arrays to store the prefix sum representing the number of valid brackets up to index i.
Now for each query [start, end], (close[end] - open[start - 1]) * 2 is the longest valid subsequence.
Below is the implementation of the above idea.
#include <bits/stdc++.h>
using namespace std;
// function to find the bracket lengths
void findBracket(vector<int> &open,
vector<int> &close, string &s) {
int n = s.size();
// to store indices of opening brackets
stack<int> st;
for (int i = 0; i < n; i++) {
if (s[i] == '(')
st.push(i);
else{
if (!st.empty()) {
close[i] = 1;
open[st.top()] = 1;
st.pop();
}
else
close[i] = 0;
}
}
// to store the correct brackets length
for (int i = 1; i < n; i++) {
close[i] += close[i - 1];
open[i] += open[i - 1];
}
}
vector<int> solveQueries(string &s,
vector<pair<int,int>> &queries) {
int n = s.size();
// to store the results of queries
vector<int> result;
// to store opening and closing brackets
vector<int> open(n+1), close(n+1);
// to store the correct brackets length
findBracket(open, close, s);
// processing the queries
for (const auto& q : queries) {
int start = q.first;
int end = q.second;
if(start == 0)
result.push_back(close[end]*2);
else
result.push_back((close[end] - open[start - 1])*2);
}
return result;
}
int main() {
string s = "())(())(())(";
vector<pair<int, int>> queries = {{4, 11},
{3, 4}, {0, 2}, {0, 4}, {1, 2}};
vector<int> ans = solveQueries(s, queries);
for(auto i:ans) {
cout<<i<<" ";
}
return 0;
}
import java.util.*;
class GfG {
// function to find the bracket lengths
static void findBracket(List<Integer> open,
List<Integer> close, String s) {
int n = s.length();
// to store indices of opening brackets
Stack<Integer> st = new Stack<>();
for (int i = 0; i < n; i++) {
if (s.charAt(i) == '(')
st.push(i);
else {
if (!st.isEmpty()) {
close.set(i, 1);
open.set(st.pop(), 1);
} else
close.set(i, 0);
}
}
// to store the correct brackets length
for (int i = 1; i < n; i++) {
close.set(i, close.get(i) + close.get(i - 1));
open.set(i, open.get(i) + open.get(i - 1));
}
}
static List<Integer> solveQueries(String s,
List<int[]> queries) {
int n = s.length();
// to store the results of queries
List<Integer> result = new ArrayList<>();
// to store opening and closing brackets
List<Integer> open = new ArrayList<>(Collections.nCopies(n + 1, 0));
List<Integer> close = new ArrayList<>(Collections.nCopies(n + 1, 0));
// to store the correct brackets length
findBracket(open, close, s);
// processing the queries
for (int[] q : queries) {
int start = q[0];
int end = q[1];
if (start == 0)
result.add(close.get(end) * 2);
else
result.add((close.get(end) - open.get(start - 1)) * 2);
}
return result;
}
public static void main(String[] args) {
String s = "())(())(())(";
List<int[]> queries = Arrays.asList(new int[]{4, 11},
new int[]{3, 4}, new int[]{0, 2}, new int[]{0, 4}, new int[]{1, 2});
List<Integer> ans = solveQueries(s, queries);
for (int i : ans) {
System.out.print(i + " ");
}
}
}
# Python program to perform queries on bracket lengths
# function to find the bracket lengths
def findBracket(open, close, s):
n = len(s)
# to store indices of opening brackets
st = []
for i in range(n):
if s[i] == '(':
st.append(i)
else:
if st:
close[i] = 1
open[st.pop()] = 1
else:
close[i] = 0
# to store the correct brackets length
for i in range(1, n):
close[i] += close[i - 1]
open[i] += open[i - 1]
def solveQueries(s, queries):
n = len(s)
# to store the results of queries
result = []
# to store opening and closing brackets
open = [0] * (n + 1)
close = [0] * (n + 1)
# to store the correct brackets length
findBracket(open, close, s)
# processing the queries
for q in queries:
start, end = q
if start == 0:
result.append(close[end] * 2)
else:
result.append((close[end] - open[start - 1]) * 2)
return result
if __name__ == "__main__":
s = "())(())(())("
queries = [(4, 11), (3, 4), (0, 2), (0, 4), (1, 2)]
ans = solveQueries(s, queries)
print(" ".join(map(str, ans)))
using System;
using System.Collections.Generic;
public class GfG {
// function to find the bracket lengths
static void FindBracket(List<int> open,
List<int> close, string s) {
int n = s.Length;
// to store indices of opening brackets
Stack<int> st = new Stack<int>();
for (int i = 0; i < n; i++) {
if (s[i] == '(')
st.Push(i);
else {
if (st.Count > 0) {
close[i] = 1;
open[st.Pop()] = 1;
} else
close[i] = 0;
}
}
// to store the correct brackets length
for (int i = 1; i < n; i++) {
close[i] += close[i - 1];
open[i] += open[i - 1];
}
}
static List<int> SolveQueries(string s,
List<Tuple<int, int>> queries) {
int n = s.Length;
// to store the results of queries
List<int> result = new List<int>();
// to store opening and closing brackets
List<int> open = new List<int>(new int[n + 1]);
List<int> close = new List<int>(new int[n + 1]);
// to store the correct brackets length
FindBracket(open, close, s);
// processing the queries
foreach (var q in queries) {
int start = q.Item1;
int end = q.Item2;
if (start == 0)
result.Add(close[end] * 2);
else
result.Add((close[end] - open[start - 1]) * 2);
}
return result;
}
static void Main(string[] args) {
string s = "())(())(())(";
List<Tuple<int, int>> queries = new List<Tuple<int, int>> {
Tuple.Create(4, 11), Tuple.Create(3, 4),
Tuple.Create(0, 2), Tuple.Create(0, 4), Tuple.Create(1, 2)
};
List<int> ans = SolveQueries(s, queries);
foreach (var i in ans) {
Console.Write(i + " ");
}
}
}
// JavaScript program to perform queries on bracket lengths
// function to find the bracket lengths
function findBracket(open, close, s) {
let n = s.length;
// to store indices of opening brackets
let st = [];
for (let i = 0; i < n; i++) {
if (s[i] === '(')
st.push(i);
else {
if (st.length > 0) {
close[i] = 1;
open[st.pop()] = 1;
} else
close[i] = 0;
}
}
// to store the correct brackets length
for (let i = 1; i < n; i++) {
close[i] += close[i - 1];
open[i] += open[i - 1];
}
}
function solveQueries(s, queries) {
let n = s.length;
// to store the results of queries
let result = [];
// to store opening and closing brackets
let open = Array(n + 1).fill(0);
let close = Array(n + 1).fill(0);
// to store the correct brackets length
findBracket(open, close, s);
// processing the queries
for (let [start, end] of queries) {
if (start === 0)
result.push(close[end] * 2);
else
result.push((close[end] - open[start - 1]) * 2);
}
return result;
}
const s = "())(())(())(";
const queries = [[4, 11], [3, 4], [0, 2], [0, 4], [1, 2]];
const ans = solveQueries(s, queries);
console.log(ans.join(" "));
Output
6 0 2 2 0
Time Complexity: O(n + q), O(1) for each query.
Auxiliary Space: O(n)