# Range Queries for Longest Correct Bracket Subsequence

Last Updated : 27 Apr, 2023

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 = ())(())(())(
Output: 10
Explanation:  Longest Correct Bracket Subsequence is ()(())(())

Input: S = ())(())(())(0
Output: 0

## Range Queries for Longest Correct Bracket Subsequence using segment trees:

To solve the problem follow the below idea:

Segment Trees can be used to solve this problem efficiently At each node of the segment tree, we store the following:

• Number of correctly matched pairs of brackets
• Number of unused open brackets
• Number of unused closed brackets

(unused open bracket – means they can’t be matched with any closing bracket, for e.g S = )( contains an unused open and an unused closed bracket) For each interval [L, R], we can match X number of unused open brackets ‘(‘ in interval [L, MID] with unused closed brackets ‘)’ in interval [MID + 1, R] where X = minimum(number of unused ‘(‘ in [L, MID], number of unused ‘)’ in [MID + 1, R]) Hence, X is also the number of correctly matched pairs built by combination. So, for interval [L, R]

• Total number of correctly matched pairs becomes the sum of correctly matched pairs in left child and correctly matched pairs in right child and number of combinations of unused ‘(‘ and unused ‘)’ from left and right child respectively

a[L, R] = a[L, MID] + a[MID + 1, R] + X

• Total number of unused open brackets becomes the sum of unused open brackets in left child and unused open brackets in right child minus X (minus – because we used X unused ‘(‘ from left child to match with unused ‘) from right child)

a[L, R] = b[L, MID] + b[MID + 1, R] – X

• Similarly, for unused closed brackets, following relation holds

a[L, R] = c[L, MID] + c[MID + 1, R] – X

where a, b and c are the representations described above for each node to be stored in

Below is the implementation of the above approach:

## C++

 `/* CPP Program to find the longest correct` `bracket subsequence in a given range */` `#include ` `using` `namespace` `std;`   `/* Declaring Structure for storing` `three values in each segment tree node */` `struct` `Node {` `    ``int` `pairs;` `    ``int` `open; ``// unused` `    ``int` `closed; ``// unused`   `    ``Node() { pairs = open = closed = 0; }` `};`   `// A utility function to get the middle index from corner` `// indexes.` `int` `getMid(``int` `s, ``int` `e) { ``return` `s + (e - s) / 2; }`   `// Returns Parent Node after merging its left and right` `// child` `Node merge(Node leftChild, Node rightChild)` `{` `    ``Node parentNode;` `    ``int` `minMatched = min(leftChild.open, rightChild.closed);` `    ``parentNode.pairs` `        ``= leftChild.pairs + rightChild.pairs + minMatched;` `    ``parentNode.open` `        ``= leftChild.open + rightChild.open - minMatched;` `    ``parentNode.closed` `        ``= leftChild.closed + rightChild.closed - minMatched;` `    ``return` `parentNode;` `}`   `// A recursive function that constructs Segment Tree` `// for string[ss..se]. si is index of current node in` `// segment tree st` `void` `constructSTUtil(``char` `str[], ``int` `ss, ``int` `se, Node* st,` `                     ``int` `si)` `{` `    ``// If there is one element in string, store it in` `    ``// current node of segment tree and return` `    ``if` `(ss == se) {`   `        ``// since it contains one element, pairs` `        ``// will be zero` `        ``st[si].pairs = 0;`   `        ``// check whether that one element is opening` `        ``// bracket or not` `        ``st[si].open = (str[ss] == ``'('` `? 1 : 0);`   `        ``// check whether that one element is closing` `        ``// bracket or not` `        ``st[si].closed = (str[ss] == ``')'` `? 1 : 0);`   `        ``return``;` `    ``}`   `    ``// If there are more than one elements, then recur` `    ``// for left and right subtrees and store the relation` `    ``// of values in this node` `    ``int` `mid = getMid(ss, se);` `    ``constructSTUtil(str, ss, mid, st, si * 2 + 1);` `    ``constructSTUtil(str, mid + 1, se, st, si * 2 + 2);`   `    ``// Merge left and right child into the Parent Node` `    ``st[si] = merge(st[si * 2 + 1], st[si * 2 + 2]);` `}`   `/* Function to construct segment tree from given` `string. This function allocates memory for segment` `tree and calls constructSTUtil() to fill the` `allocated memory */` `Node* constructST(``char` `str[], ``int` `n)` `{` `    ``// Allocate memory for segment tree`   `    ``// Height of segment tree` `    ``int` `x = (``int``)(``ceil``(log2(n)));`   `    ``// Maximum size of segment tree` `    ``int` `max_size = 2 * (``int``)``pow``(2, x) - 1;`   `    ``// Declaring array of structure Allocate memory` `    ``Node* st = ``new` `Node[max_size];`   `    ``// Fill the allocated memory st` `    ``constructSTUtil(str, 0, n - 1, st, 0);`   `    ``// Return the constructed segment tree` `    ``return` `st;` `}`   `/* A Recursive function to get the desired` `Maximum Sum Sub-Array,` `The following are parameters of the function-`   `st     --> Pointer to segment tree` `si --> Index of the segment tree Node` `ss & se --> Starting and ending indexes of the` `            ``segment represented by` `                ``current Node, i.e., tree[index]` `qs & qe --> Starting and ending indexes of query range */` `Node queryUtil(Node* st, ``int` `ss, ``int` `se, ``int` `qs, ``int` `qe,` `               ``int` `si)` `{` `    ``// No overlap` `    ``if` `(ss > qe || se < qs) {`   `        ``// returns a Node for out of bounds condition` `        ``Node nullNode;` `        ``return` `nullNode;` `    ``}`   `    ``// Complete overlap` `    ``if` `(ss >= qs && se <= qe) {` `        ``return` `st[si];` `    ``}`   `    ``// Partial Overlap Merge results of Left` `    ``// and Right subtrees` `    ``int` `mid = getMid(ss, se);` `    ``Node left = queryUtil(st, ss, mid, qs, qe, si * 2 + 1);` `    ``Node right` `        ``= queryUtil(st, mid + 1, se, qs, qe, si * 2 + 2);`   `    ``// merge left and right subtree query results` `    ``Node res = merge(left, right);` `    ``return` `res;` `}`   `/* Returns the maximum length correct bracket` `subsequencebetween start and end` `It mainly uses queryUtil(). */` `int` `query(Node* st, ``int` `qs, ``int` `qe, ``int` `n)` `{` `    ``Node res = queryUtil(st, 0, n - 1, qs, qe, 0);`   `    ``// since we are storing numbers pairs` `    ``// and have to return maximum length, hence` `    ``// multiply no of pairs by 2` `    ``return` `2 * res.pairs;` `}`   `// Driver Code` `int` `main()` `{` `    ``char` `str[] = ``"())(())(())("``;` `    ``int` `n = ``strlen``(str);`   `    ``// Build segment tree from given string` `    ``Node* st = constructST(str, n);`   `      ``// Function call` `    ``int` `startIndex = 0, endIndex = 11;` `    ``cout << ``"Maximum Length Correct Bracket"` `            ``" Subsequence between "` `         ``<< startIndex << ``" and "` `<< endIndex << ``" = "` `         ``<< query(st, startIndex, endIndex, n) << endl;`   `    ``startIndex = 1, endIndex = 2;` `    ``cout << ``"Maximum Length Correct Bracket"` `            ``" Subsequence between "` `         ``<< startIndex << ``" and "` `<< endIndex << ``" = "` `         ``<< query(st, startIndex, endIndex, n) << endl;`   `    ``return` `0;` `}`

## Java

 `// Java Program to find the longest correct bracket ` `// subsequence in a given range ` `import` `java.util.*;` `import` `java.lang.*;` `import` `java.io.*;`   `// Declaring Structure for storing three values in each segment tree node` `class` `Node {` `    ``int` `pairs;` `    ``int` `open; ``// unused` `    ``int` `closed; ``// unused` ` `  `    ``Node() {` `        ``pairs = ``0``;` `        ``open = ``0``;` `        ``closed = ``0``;` `    ``}` `}`   `class` `SegmentTree {` `    ``Node[] st;` `    ``int` `n;` ` `  `    ``// A utility function to get the middle index from corner indexes.` `    ``int` `getMid(``int` `s, ``int` `e) {` `        ``return` `s + (e - s) / ``2``;` `    ``}` ` `  `    ``// Returns Parent Node after merging its left and right child` `    ``Node merge(Node leftChild, Node rightChild) {` `        ``Node parentNode = ``new` `Node();` `        ``int` `minMatched = Math.min(leftChild.open, rightChild.closed);` `        ``parentNode.pairs = leftChild.pairs + rightChild.pairs + minMatched;` `        ``parentNode.open = leftChild.open + rightChild.open - minMatched;` `        ``parentNode.closed = leftChild.closed + rightChild.closed - minMatched;` `        ``return` `parentNode;` `    ``}` ` `  `    ``// A recursive function that constructs Segment Tree for string[ss..se].` `    ``// si is index of current node in segment tree st` `    ``void` `constructSTUtil(String str, ``int` `ss, ``int` `se, ``int` `si) {` `        ``// If there is one element in string, store it in current node of ` `        ``// segment tree and return` `        ``if` `(ss == se) {` `            ``// since it contains one element, pairs will be zero` `            ``st[si].pairs = ``0``;` `            ``// check whether that one element is opening bracket or not` `            ``st[si].open = (str.charAt(ss) == ``'('``) ? ``1` `: ``0``;` `            ``// check whether that one element is closing bracket or not` `            ``st[si].closed = (str.charAt(ss) == ``')'``) ? ``1` `: ``0``;` `            ``return``;` `        ``}` ` `  `        ``// If there are more than one elements, then recur for left and right ` `        ``// subtrees and store the relation of values in this node` `        ``int` `mid = getMid(ss, se);` `        ``constructSTUtil(str, ss, mid, si * ``2` `+ ``1``);` `        ``constructSTUtil(str, mid + ``1``, se, si * ``2` `+ ``2``);` ` `  `        ``// Merge left and right child into the Parent Node` `        ``st[si] = merge(st[si * ``2` `+ ``1``], st[si * ``2` `+ ``2``]);` `    ``}` ` `  `    ``// Function to construct segment tree from given string.` `    ``// This function allocates memory for segment tree and calls ` `    ``// constructSTUtil() to fill the allocated memory` `    ``void` `constructST(String str) {` `        ``// Allocate memory for segment tree` `        ``// Height of segment tree` `        ``int` `x = (``int``) (Math.ceil(Math.log(n) / Math.log(``2``)));` ` `  `        ``// Maximum size of segment tree` `        ``int` `max_size = ``2` `* (``int``) Math.pow(``2``, x) - ``1``;` ` `  `        ``st = ``new` `Node[max_size];` `        ``for` `(``int` `i = ``0``; i < max_size; i++)` `            ``st[i] = ``new` `Node();` ` `  `        ``// Fill the allocated memory st` `        ``constructSTUtil(str, ``0``, n - ``1``, ``0``);` `    ``}` ` `  `    ``// A Recursive function to get the desired Maximum Sum Sub-Array,` `    ``// The following are parameters of the function-` `    ``// st     --> Pointer to segment tree` `    ``// si --> Index of the segment tree Node` `    ``// ss & se --> Starting and ending indexes of the segment ` `    ``// represented by current Node, i.e., tree[index]` `    ``// qs & qe --> Starting and ending indexes of query range` `    ``Node queryUtil(``int` `ss, ``int` `se, ``int` `qs, ``int` `qe, ``int` `si) {` `        ``// No overlap` `        ``if` `(ss > qe || se < qs)` `            ``// returns a Node for out of bounds condition` `            ``return` `new` `Node();` ` `  `        ``// Complete overlap` `        ``if` `(ss >= qs && se <= qe)` `            ``return` `st[si];` ` `  `        ``// Partial Overlap Merge results of Left and Right subtrees` `        ``int` `mid = getMid(ss, se);` `        ``Node left = queryUtil(ss, mid, qs, qe, si * ``2` `+ ``1``);` `        ``Node right = queryUtil(mid + ``1``, se, qs, qe, si * ``2` `+ ``2``);` `        ``return` `merge(left, right);` `    ``}` ` `  `    ``// The function to get the maximum length of correct bracket subsequence` `    ``// for given range. The following are parameters of the function-` `    ``// st --> Pointer to segment tree` `    ``// qs & qe --> Starting and ending indexes of query range` `    ``int` `query(``int` `qs, ``int` `qe) {` `        ``Node node = queryUtil(``0``, n - ``1``, qs, qe, ``0``);` `        ``return` `2` `* node.pairs;` `    ``}` ` `  `    ``// Driver code` `    ``public` `static` `void` `main(String args[]) {` `        ``String str = ``"())(())(())("``;` `        ``int` `n = str.length();` `        ``SegmentTree tree = ``new` `SegmentTree();` `        ``tree.n = n;` `        ``tree.constructST(str);` `        ``int` `qs = ``0``;` `        ``int` `qe = n - ``1``;` `        ``System.out.println(``"Maximum Length Correct Bracket Subsequence between "` `+ qs + ``" and "` `+ qe + ``" = "` `+ tree.query(qs, qe));` ` `  `        ``qs = ``1``;` `        ``qe = ``2``;` `        ``System.out.println(``"Maximum Length Correct Bracket Subsequence between "` `+ qs + ``" and "` `+ qe + ``" = "` `+ tree.query(qs, qe));` `    ``}` `}`

## Python3

 `# Python Program to find the longest correct bracket ` `# subsequence in a given range ` `import` `math` `# Declaring Structure for storing three values in each segment tree node` `class` `Node:` `    ``def` `__init__(``self``):` `        ``self``.pairs ``=` `0` `        ``self``.``open` `=` `0` `# unused` `        ``self``.closed ``=` `0` `# unused`   `# A utility function to get the middle index from corner indexes.` `def` `getMid(s: ``int``, e: ``int``) ``-``> ``int``:` `    ``return` `s ``+` `(e ``-` `s) ``/``/` `2`   `# Returns Parent Node after merging its left and right child` `def` `merge(leftChild: Node, rightChild: Node) ``-``> Node:` `    ``parentNode ``=` `Node()` `    ``minMatched ``=` `min``(leftChild.``open``, rightChild.closed)` `    ``parentNode.pairs ``=` `leftChild.pairs ``+` `rightChild.pairs ``+` `minMatched` `    ``parentNode.``open` `=` `leftChild.``open` `+` `rightChild.``open` `-` `minMatched` `    ``parentNode.closed ``=` `leftChild.closed ``+` `rightChild.closed ``-` `minMatched` `    ``return` `parentNode`   `# A recursive function that constructs Segment Tree for string[ss..se].` `# si is index of current node in segment tree st` `def` `constructSTUtil(``str``: ``str``, ss: ``int``, se: ``int``, st: ``list``, si: ``int``):` `    ``# If there is one element in string, store it in current node of segment tree and return` `    ``if` `ss ``=``=` `se:` `        ``# since it contains one element, pairs will be zero` `        ``st[si].pairs ``=` `0` `        ``# check whether that one element is opening bracket or not` `        ``st[si].``open` `=` `1` `if` `str``[ss] ``=``=` `'('` `else` `0` `        ``# check whether that one element is closing bracket or not` `        ``st[si].closed ``=` `1` `if` `str``[ss] ``=``=` `')'` `else` `0` `        ``return` `    ``# If there are more than one elements, then recur for left and right subtrees` `    ``# and store the relation of values in this node` `    ``mid ``=` `getMid(ss, se)` `    ``constructSTUtil(``str``, ss, mid, st, si ``*` `2` `+` `1``)` `    ``constructSTUtil(``str``, mid ``+` `1``, se, st, si ``*` `2` `+` `2``)` `    ``# Merge left and right child into the Parent Node` `    ``st[si] ``=` `merge(st[si ``*` `2` `+` `1``], st[si ``*` `2` `+` `2``])`   `# Function to construct segment tree from given string.` `# This function allocates memory for segment tree and calls constructSTUtil()` `# to fill the allocated memory` `def` `constructST(``str``: ``str``, n: ``int``) ``-``> ``list``:` `    ``# Allocate memory for segment tree` `    ``# Height of segment tree` `    ``x ``=` `int``(math.ceil(math.log2(n)))` `    ``# Maximum size of segment tree` `    ``max_size ``=` `2` `*` `int``(``2` `*``*` `x) ``-` `1` `    ``# Declaring array of structure Allocate memory` `    ``st ``=` `[Node() ``for` `_ ``in` `range``(max_size)]` `    ``# Fill the allocated memory st` `    ``constructSTUtil(``str``, ``0``, n ``-` `1``, st, ``0``)` `    ``# Return the constructed segment tree` `    ``return` `st`   `# A Recursive function to get the desired Maximum Sum Sub-Array,` `# The following are parameters of the function-` `# st     --> Pointer to segment tree` `# si --> Index of the segment tree Node` `# ss & se --> Starting and ending indexes of the segment ` `# represented by current Node, i.e., tree[index]` `# qs & qe --> Starting and ending indexes of query range` `def` `queryUtil(st: ``list``, ss: ``int``, se: ``int``, qs: ``int``, qe: ``int``, si: ``int``) ``-``> Node:` `    ``# No overlap` `    ``if` `ss > qe ``or` `se < qs:` `        ``# returns a Node for out of bounds condition` `        ``return` `Node()` `    ``# Complete overlap` `    ``if` `ss >``=` `qs ``and` `se <``=` `qe:` `        ``return` `st[si]` `    ``# Partial Overlap Merge results of Left and Right subtrees` `    ``mid ``=` `getMid(ss, se)` `    ``left ``=` `queryUtil(st, ss, mid, qs, qe, si ``*` `2` `+` `1``)` `    ``right ``=` `queryUtil(st, mid ``+` `1``, se, qs, qe, si ``*` `2` `+` `2``)` `    ``return` `merge(left, right)`   `# The function to get the maximum length of correct bracket subsequence` `# for given range. The following are parameters of the function-` `# st --> Pointer to segment tree` `# qs & qe --> Starting and ending indexes of query range` `def` `query(st: ``list``, n: ``int``, qs: ``int``, qe: ``int``) ``-``> ``int``:` `    ``node ``=` `queryUtil(st, ``0``, n ``-` `1``, qs, qe, ``0``)` `    ``return` `2` `*` `node.pairs`   `# Driver code` `def` `main():` `    ``str` `=` `"())(())(())("` `    ``n ``=` `len``(``str``)` `    ``st ``=` `constructST(``str``, n)` `    ``qs ``=` `0` `    ``qe ``=` `n ``-` `1` `    ``print``(``"Maximum Length Correct Bracket Subsequence between"``, qs, ``"and"``, qe, ``"="``, query(st, n, qs, qe))`   `    ``qs ``=` `1` `    ``qe ``=` `2` `    ``print``(``"Maximum Length Correct Bracket Subsequence between"``, qs, ``"and"``, qe, ``"="``, query(st, n, qs, qe))`   `if` `__name__ ``=``=` `'__main__'``:` `    ``main()` `# This code is contributed by Vikram_Shirsat`

## Javascript

 `// Javascript Program to find the longest correct bracket ` `// subsequence in a given range ` `class Node {` `  ``constructor() {` `    ``this``.pairs = 0;` `    ``this``.open = 0; ``// unused` `    ``this``.closed = 0; ``// unused` `  ``}` `}`   `// A utility function to get the middle index from corner indexes.` `function` `getMid(s, e) {` `  ``return` `s + Math.floor((e - s) / 2);` `}`   `// Returns Parent Node after merging its left and right child` `function` `merge(leftChild, rightChild) {` `  ``const parentNode = ``new` `Node();` `  ``const minMatched = Math.min(leftChild.open, rightChild.closed);` `  ``parentNode.pairs = leftChild.pairs + rightChild.pairs + minMatched;` `  ``parentNode.open = leftChild.open + rightChild.open - minMatched;` `  ``parentNode.closed = leftChild.closed + rightChild.closed - minMatched;` `  ``return` `parentNode;` `}`     `// A recursive function that constructs Segment Tree for string[ss..se].` `// si is index of current node in segment tree st` `function` `constructSTUtil(str, ss, se, st, si) {` `    ``// If there is one element in string, store it in current node of segment tree and return` `  ``if` `(ss === se) {` `    ``// since it contains one element, pairs will be zero` `    ``st[si].pairs = 0;` `    ``// check whether that one element is opening bracket or not` `    ``st[si].open = str[ss] === ``'('` `? 1 : 0;` `    ``// check whether that one element is closing bracket or not` `    ``st[si].closed = str[ss] === ``')'` `? 1 : 0;` `    ``return``;` `  ``}` `    ``// If there are more than one elements, then recur for left and right subtrees` `    ``// and store the relation of values in this node` `  ``const mid = getMid(ss, se);` `  ``constructSTUtil(str, ss, mid, st, si * 2 + 1);` `  ``constructSTUtil(str, mid + 1, se, st, si * 2 + 2);` `  ``// Merge left and right child into the Parent Node` `  ``st[si] = merge(st[si * 2 + 1], st[si * 2 + 2]);` `}`   `// Function to construct segment tree from given string.` `// This function allocates memory for segment tree and calls constructSTUtil()` `// to fill the allocated memory` `function` `constructST(str, n) {` `   ``// Allocate memory for segment tree` `  ``// Height of segment tree` `  ``const x = Math.ceil(Math.log2(n));` `  ``// Maximum size of segment tree` `  ``const max_size = 2 * Math.pow(2, x) - 1;` `  ``// Declaring array of structure Allocate memory` `  ``const st = Array(max_size).fill().map(_ => ``new` `Node());` `  ``// Fill the allocated memory st` `  ``constructSTUtil(str, 0, n - 1, st, 0);` `  ``// Return the constructed segment tree` `  ``return` `st;` `}`     `// A Recursive function to get the desired Maximum Sum Sub-Array,` `// The following are parameters of the function-` `// st     --> Pointer to segment tree` `// si --> Index of the segment tree Node` `// ss & se --> Starting and ending indexes of the segment ` `// represented by current Node, i.e., tree[index]` `// qs & qe --> Starting and ending indexes of query range` `function` `queryUtil(st, ss, se, qs, qe, si) {` `  ``if` `(ss > qe || se < qs) {` `    ``return` `new` `Node();` `  ``}` `  ``if` `(ss >= qs && se <= qe) {` `    ``return` `st[si];` `  ``}` `  ``const mid = getMid(ss, se);` `  ``const left = queryUtil(st, ss, mid, qs, qe, si * 2 + 1);` `  ``const right = queryUtil(st, mid + 1, se, qs, qe, si * 2 + 2);` `  ``return` `merge(left, right);` `}`     `// The function to get the maximum length of correct bracket subsequence` `// for given range. The following are parameters of the function-` `// st --> Pointer to segment tree` `// qs & qe --> Starting and ending indexes of query range` `function` `query(st, n, qs, qe) {` `  ``const node = queryUtil(st, 0, n - 1, qs, qe, 0);` `  ``return` `2 * node.pairs;` `}`   `// Driver code` `function` `main() {` `  ``const str = ``"())(())(())("``;` `  ``const n = str.length;` `  ``const st = constructST(str, n);` `  ``let qs = 0;` `  ``let qe = n - 1;` `  ``console.log(`Maximum Length Correct Bracket Subsequence between \${qs} and \${qe} = \${query(st, n, qs, qe)}`);`   `  ``qs = 1;` `  ``qe = 2;` `  ``console.log(`Maximum Length Correct Bracket Subsequence between \${qs} and \${qe} = \${query(st, n, qs, qe)}`);` `}`   `main();`   `// This code is contributed by sdeadityasharma`

## C#

 `// C# Program to find the longest correct bracket ` `// subsequence in a given range `   `using` `System;` `// Declaring Structure for storing three values in each segment tree node    // A utility function to get the middle index from corner indexes.` `class` `Node {` `    ``public` `int` `pairs;` `    ``public` `int` `open;` `    ``public` `int` `closed;`   `    ``public` `Node() {` `        ``pairs = 0;` `        ``open = 0;` `        ``closed = 0;` `    ``}` `}`   `class` `SegmentTree {` `    ``public` `Node[] st;` `    ``public` `int` `n;` `    ``// A utility function to get the middle index from corner indexes.` `    ``int` `getMid(``int` `s, ``int` `e) {` `        ``return` `s + (e - s) / 2;` `    ``}` ` ``// Returns Parent Node after merging its left and right child` `    ``Node merge(Node leftChild, Node rightChild) {` `        ``Node parentNode = ``new` `Node();` `        ``int` `minMatched = Math.Min(leftChild.open, rightChild.closed);` `        ``parentNode.pairs = leftChild.pairs + rightChild.pairs + minMatched;` `        ``parentNode.open = leftChild.open + rightChild.open - minMatched;` `        ``parentNode.closed = leftChild.closed + rightChild.closed - minMatched;` `        ``return` `parentNode;` `    ``}` `    ``// A recursive function that constructs Segment Tree for string[ss..se].` `    ``// si is index of current node in segment tree st` `    ``void` `constructSTUtil(``string` `str, ``int` `ss, ``int` `se, ``int` `si) {` `         ``// If there is one element in string, store it in current node of ` `        ``// segment tree and return` `        `  `        ``if` `(ss == se) {` `                   ``// since it contains one element, pairs will be zero` `            ``st[si].pairs = 0;` `            ``// check whether that one element is opening bracket or not` `            ``st[si].open = (str[ss] == ``'('``) ? 1 : 0;` `              ``// check whether that one element is closing bracket or not` `        ``// If there are more than one elements, then recur for left and right ` `        ``// subtrees and store the relation of values in this node` `            ``st[si].closed = (str[ss] == ``')'``) ? 1 : 0;` `            ``return``;` `        ``}`   `        ``// If there are more than one elements, then recur for left and right ` `        ``// subtrees and store the relation of values in this node` `        ``int` `mid = getMid(ss, se);` `        ``constructSTUtil(str, ss, mid, si * 2 + 1);` `        ``constructSTUtil(str, mid + 1, se, si * 2 + 2);` ` ``// Merge left and right child into the Parent Node` `        ``st[si] = merge(st[si * 2 + 1], st[si * 2 + 2]);` `    ``}` `    ``// Function to construct segment tree from given string.` `    ``// This function allocates memory for segment tree and calls ` `    ``// constructSTUtil() to fill the allocated memory` `    ``public` `void` `constructST(``string` `str) {` `          ``// Allocate memory for segment tree` `        ``// Height of segment tree` `        ``int` `x = (``int``) Math.Ceiling(Math.Log(n) / Math.Log(2));` `         ``// Maximum size of segment tree` `        ``int` `max_size = 2 * (``int``) Math.Pow(2, x) - 1;`   `        ``st = ``new` `Node[max_size];` `        ``for` `(``int` `i = 0; i < max_size; i++)` `            ``st[i] = ``new` `Node();` `  ``// Fill the allocated memory st` `        ``constructSTUtil(str, 0, n - 1, 0);` `    ``}` `    ``// A Recursive function to get the desired Maximum Sum Sub-Array,` `    ``// The following are parameters of the function-` `    ``// st     --> Pointer to segment tree` `    ``// si --> Index of the segment tree Node` `    ``// ss & se --> Starting and ending indexes of the segment ` `    ``// represented by current Node, i.e., tree[index]` `    ``// qs & qe --> Starting and ending indexes of query range` `    ``Node queryUtil(``int` `ss, ``int` `se, ``int` `qs, ``int` `qe, ``int` `si) {` `        ``// No overlap` `        ``if` `(ss > qe || se < qs)` `         ``// returns a Node for out of bounds condition` `            ``return` `new` `Node();`   `        ``if` `(ss >= qs && se <= qe)` `            ``return` `st[si];`   `        ``int` `mid = getMid(ss, se);` `        ``Node left = queryUtil(ss, mid, qs, qe, si * 2 + 1);` `        ``Node right = queryUtil(mid + 1, se, qs, qe, si * 2 + 2);` `        ``return` `merge(left, right);` `    ``}` ` `  `     `  `    ``// The function to get the maximum length of correct bracket subsequence` `    ``// for given range. The following are parameters of the function-` `    ``// st --> Pointer to segment tree` `    ``// qs & qe --> Starting and ending indexes of query range` `    ``public` `int` `query(``int` `qs, ``int` `qe) {` `        `  `        ``Node node = queryUtil(0, n - 1, qs, qe, 0);` `        ``return` `2 * node.pairs;` `    ``}` `//Driver code` `    ``public` `static` `void` `Main(``string``[] args) {` `        ``string` `str = ``"())(())(())("``;` `        ``int` `n = str.Length;` `        ``SegmentTree tree = ``new` `SegmentTree();` `        ``tree.n = n;` `        ``tree.constructST(str);` `        ``int` `qs = 0;` `        ``int` `qe = n - 1;` `        ``Console.WriteLine(``"Maximum Length Correct Bracket Subsequence between "` `+ qs + ``" and "` `+ qe + ``" = "` `+ tree.query(qs, qe));` `        `  `        ``qs = 1;` `        ``qe = 2;` `        ``Console.WriteLine(``"Maximum Length Correct Bracket Subsequence between "` `+ qs + ``" and "` `+ qe + ``" = "` `+ tree.query(qs, qe));` `    ``}` `}`

Output

```Maximum Length Correct Bracket Subsequence between 0 and 11 = 10
Maximum Length Correct Bracket Subsequence between 1 and 2 = 0```

Time complexity: O(N*log N), where N is the size of the string
Auxiliary Space: O(N)

Previous
Next