You are given a bracket sequence ?s consisting of ?n opening '(' and closing ')' brackets.
A regular bracket sequence is a bracket sequence that can be transformed into a correct arithmetic expression by inserting characters '1' and '+' between the original characters of the sequence. For example, bracket sequences "()()", "(())" are regular (the resulting expressions are: "(1)+(1)", "((1+1)+1)"), and ")(" and "(" are not.
You can change the type of some bracket ??si. It means that if ??=si= ')' then you can change it to '(' and vice versa.
Your task is to calculate the number of positions ?i such that if you change the type of the ?i-th bracket, then the resulting bracket sequence becomes regular.
Input
The first line of the input contains one integer ?n (1≤?≤1061≤n≤106) — the length of the bracket sequence.
The second line of the input contains the string ?s consisting of ?n opening '(' and closing ')' brackets.
Output
Print one integer — the number of positions ?i such that if you change the type of the ?i-th bracket, then the resulting bracket sequence becomes regular.
Examples
input
Copy
6 (((())
output
Copy
3
input
Copy
6 ()()()
output
Copy
0
input
Copy
1 )
output
Copy
0
input
Copy
8 )))(((((
output
Copy
0
题意:
给你一串括号序列,允许改动一个位置的括号(也就是‘(’改为‘)’,反过来也行),问你共有多少种方法,使得最终得到的括号合法。
思路:
我们从第一个字符跑到最后一个字符,对于每一个位置,我们只需要判断该位置之前的‘(’的数目和该位置之后的‘)’的数目,只有二者之差为1,该位置的字符才能改动,进而得到合法的序列。
另外,要注意的是在计算某个位置之前的‘(’的数目的时候,如果出现左括号数量已经小于右括号数量,那么后面所有的数目都要设置为-1;
代码中有更针对性的解释:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 1e6 + 100;
char st[maxn];
int dl[maxn], dr[maxn];
int main()
{
//freopen("in.txt", "r", stdin);
int n;
while(cin >> n && n)
{
scanf("%s", st + 1);
dl[0] = dr[n + 1] = 0; //先初始化两边界
int num = 0;
for(int i = 1; i <= n; ++ i)
{
if(st[i] == '(')
num ++;
else
num --;
if(num < 0 || dl[i - 1] < 0) //判断是否出现不可挽回的非法现象,也就是中途是否出现num < 0 的情况,只要出现一次,之后也就全都是非法现象了
dl[i] = -1;
else
dl[i] = num;
}
num = 0;
for(int i = n; i >= 1; -- i) //同理
{
if(st[i] == ')')
num ++;
else
num --;
if(num < 0 || dr[i + 1] < 0)
dr[i] = -1;
else
dr[i] = num;
}
int ans = 0;
for(int i = 1; i <= n; ++ i)
{
if(dl[i - 1] >= 0 && dr[i + 1] >= 0) //只有两端都没有出现过非法现象才行
{
int t = dl[i - 1] - dr[i + 1];
if(t == 1 && st[i] == '(') //只有差为1,或者-1才行
ans ++;
else if(t == -1 && st[i] == ')')
ans ++;
}
}
cout << ans << endl;
}
return 0;
}

本文介绍了一种算法,用于计算通过改变一个括号位置使序列合法的方法数。算法通过跟踪括号平衡状态,确保修改后的序列形成有效的算术表达式。

430

被折叠的 条评论
为什么被折叠?



