📜  平衡括号中涉及的对

📅  最后修改于: 2021-04-16 08:45:25             🧑  作者: Mango

给定字符串方括号,任务是找到给定范围内平衡序列中涉及的方括号对的数量。

例子 :

Input : ((())(()
Range : 1 5
Range : 3 8
Output : 2
         2
Explanation :  In range 1 to 5 ((()), 
there are the two pairs. In range 3 to 8 ())
((), there are the two pairs.

Input : )()()))
Range : 1 2
Range : 4 7
Output : 0
         1
Explanation :  In range 1 to 2 )( there 
is no any pair. In range 4 to 7 ())), 
there is the only pair

先决条件:段树

方法 :
在此,在段树中,对于每个节点,保留一些简单的元素,例如整数或集合或向量等。
对于每个节点,请保留三个整数:
1. t =间隔的答案。
2. o =删除括号后,在此间隔白色长度t中属于正确括号序列的那些剩余的左括号’(’)的数量。
3. c =删除括号后,在此间隔白色长度t中属于正确括号序列的那些括号之后剩余的“)”个括号的数量。
现在,有了这些变量,就可以使用段树轻松地查询查询。

下面是上述方法的实现:

C++
// CPP code to find the number of pairs
// involved in balanced parantheses
#include 
using namespace std;
  
// Our struct node
struct node {
      
    // three variables required
    int t, o, c;
};
  
// Declare array of nodes of very big
// size which acts as segment tree here.
struct node tree_arr[5 * 1000];
  
// To bulid a segment tree we pass 1 as
// 'id' 0 as 'l' and l as 'n'.
// Here, we consider query's interval as [x, y)
void build(int id, int l, int r, string s)
{
    /* this base condition is common to 
       build any segment tree*/
    // This is the base
    // Only one element left
    if (r - l < 2) {
          
        // If that element is open bracket
        if (s[l] == '(')
            tree_arr[id].o = 1;
          
        // If that element is open bracket
        else
            tree_arr[id].c = 1;
        return;
    }
  
    // Next three lines are common 
    // for any segment tree.
    int mid = (l + r) / 2;
      
    // for left tree
    build(2 * id, l, mid, s); 
      
    // for right tree
    build(2 * id + 1, mid, r, s);
  
    // Here we take minimum of left tree
    // opening brackets and right tree
    // closing brackets
    int tmp = min(tree_arr[2 * id].o, 
                  tree_arr[2 * id + 1].c);
  
    // we add that to our answer.
    tree_arr[id].t = tree_arr[2 * id].t + 
              tree_arr[2 * id + 1].t + tmp;
  
    // Remove the answer from opening brackets
    tree_arr[id].o = tree_arr[2 * id].o + 
               tree_arr[2 * id + 1].o - tmp;
  
    // Remove the answer from opening brackets
    tree_arr[id].c = tree_arr[2 * id].c + 
               tree_arr[2 * id + 1].c - tmp;
}
  
// This will return the answer for each query.
// Here we consider query's interval as [x, y)
node segment(int x, int y, int id, 
             int l, int r, string s)
{
    // If the given interval is out of range
    if (l >= y || x >= r) {
        struct node tem;
        tem.t = 0;
        tem.o = 0;
        tem.c = 0;
        return tem;
    }
  
    // If the given interval completely lies
    if (x <= l && r <= y)
        return tree_arr[id];
  
    // Next three lines are common for 
    // any segment tree.
    int mid = (l + r) / 2;
      
    // For left tree
    struct node a = 
           segment(x, y, 2 * id, l, mid, s);
      
    // For right tree
    struct node b = 
           segment(x, y, 2 * id + 1, mid, r, s);
  
    // Same as made in build function
    int temp;
    temp = min(a.o, b.c);
    struct node vis;
    vis.t = a.t + b.t + temp;
    vis.o = a.o + b.o - temp;
    vis.c = a.c + b.c - temp;
  
    return vis;
}
  
// Driver code
int main()
{
    string s = "((())(()";
    int n = s.size();
  
    // range for query
    int a = 3, b = 8;
      
    build(1, 0, n, s);
      
    // Here we consider query's interval as [a, b)
    // We subtract 1 from 'a' because indexes start
    // from 0.
    struct node p = segment(a-1, b, 1, 0, n, s);
    cout << p.t << endl;
      
    return 0;
}


Python3
# Python3 code to find the number of pairs
# involved in balanced parantheses
  
# Our struct node
class node :
    def __init__(self):
        # three variables required
        self.t = 0
        self.o = 0
        self.c = 0
  
# Declare array of nodes of very big
# size which acts as segment tree here.
tree_arr = [node()]*(5 * 1000)
  
# To bulid a segment tree we pass 1 as
# 'id' 0 as 'l' and l as 'n'.
# Here, we consider query's interval as [x, y)
def build(id, l, r, s):
    global tree_arr
      
    tree_arr[id] = node()
      
    # this base condition is common to 
    # build any segment tree
    # This is the base
    # Only one element left
    if (r - l < 2) :
          
        # If that element is open bracket
        if (s[l] == "("):
            tree_arr[id].o = 1
          
        # If that element is open bracket
        else:
            tree_arr[id].c = 1
        return
  
    # Next three lines are common 
    # for any segment tree.
    mid = int( (l + r) / 2)
      
    # for left tree
    build(2 * id, l, mid, s) 
      
    # for right tree
    build(2 * id + 1, mid, r, s)
  
    # Here we take minimum of left tree
    # opening brackets and right tree
    # closing brackets
    tmp = min(tree_arr[2 * id].o, 
                tree_arr[2 * id + 1].c)
    # we add that to our answer.
    tree_arr[id].t = tree_arr[2 * id].t + \
                    tree_arr[2 * id + 1].t + tmp
  
    # Remove the answer from opening brackets
    tree_arr[id].o = tree_arr[2 * id].o + \
                    tree_arr[2 * id + 1].o - tmp
  
    # Remove the answer from opening brackets
    tree_arr[id].c = tree_arr[2 * id].c + \
                    tree_arr[2 * id + 1].c - tmp
  
# This will return the answer for each query.
# Here we consider query's interval as [x, y)
def segment(x, y, id, l, r, s):
      
    global tree_arr
      
    # If the given interval is out of range
    if (l >= y or x >= r) :
        tem= node()
        tem.t = 0
        tem.o = 0
        tem.c = 0
        return tem
      
    # If the given interval completely lies
    if (x <= l and r <= y):
        return tree_arr[id]
  
    # Next three lines are common for 
    # any segment tree.
    mid = int((l + r) / 2)
      
    # For left tree
    a = segment(x, y, 2 * id, l, mid, s)
      
    # For right tree
    b = segment(x, y, 2 * id + 1, mid, r, s)
  
    # Same as made in build function
    temp= 0
    temp = min(a.o, b.c)
    vis = node()
      
    vis.t = a.t + b.t + temp
    vis.o = a.o + b.o - temp
    vis.c = a.c + b.c - temp
    return vis
  
# Driver code
  
s = "((())(()"
n = len(s)
  
# range for query
a = 3
b = 8
      
build(1, 0, n, s)
      
# Here we consider query's interval as [a, b)
# We subtract 1 from 'a' because indexes start
# from 0.
p = segment(a-1, b, 1, 0, n, s)
print(p.t )
  
# This code is contributed by Arnab Kundu


输出:
2