给定字符串方括号,任务是找到给定范围内平衡序列中涉及的方括号对的数量。
例子 :
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