题目描述
You are working with a strange text editor for texts consisting only of open and close parentheses. The editor accepts the following three keys as editing commands to modify the text kept in it.
·‘(’ appends an open parenthesis (‘(’) to the end of the text.
·‘)’ appends a close parenthesis (‘)’) to the end of the text.
·‘-’ removes the last character of the text.
A balanced string is one of the following.
·“()”
·“(X)” where X is a balanced string
·“XY” where both X and Y are balanced strings
Initially, the editor keeps an empty text. You are interested in the number of balanced substrings in the text kept in the editor after each of your key command inputs. Note that, for the same balanced substring occurring twice or more, their occurrences should be counted separately. Also note that, when some balanced substrings are inside a balanced substring, both the inner and outer balanced substrings should be counted.
输入
The input consists of a single test case given in a line containing a number of characters, each of which is a command key to the editor, that is, either ‘(’, ‘)’, or ‘-’. The number of characters does not exceed 200 000. They represent a key input sequence to the editor.
It is guaranteed that no ‘-’ command comes when the text is empty.
输出
Print the numbers of balanced substrings in the text kept in the editor after each of the key command inputs are applied, each in one line. Thus, the number of output lines should be the same as the number of characters in the input line.
样例输入
【样例1】
(()())---)
【样例2】
()--()()----)(()()))
样例输出
【样例1】
0
0
1
1
3
4
3
1
1
2
【样例2】
0
1
0
0
0
1
1
3
1
1
0
0
0
0
0
1
1
3
4
4
思路
栈:存 ’ ( ’ 的位置;
dp [ i ] : 以第 i 个字符为结尾的平衡串有多少个。
match[ i ]:字符 s [ i ] 对应的左括号的位置,如果 s [ i ] 是右括号则 match [ i ] = 0;
因为 ’ - ’ 可以删掉结尾的字符,所以我们可以设置一个变量 cnt 充当 dp 和 match 的下标,如果遇到 ’ - ’ ,就将 cnt-- , 同时更新栈和答案
如果 s [ i ] == ‘(’ 那么显然 dp [ cnt ] = 0,( 因为以 ‘(’ 结尾的字符串不会是平衡串 );
如果 s [ i ] == ‘)’ 那么dp [ cnt ] = dp [ q.top() - 1 ] + 1(如果栈不为空,那么栈顶就是对应的左括号的位置,位置 - 1 是看此对应左括号左边是左括号还是右括号,如果是左括号则没有连续的平衡串,否则有连续的平衡串);
如果 s [ i ] == ‘-’ ,那么 cnt-- ,更新栈和答案(把栈里因为下标移动加进来的重新移出去,或者移出去的重新加进来)
对了,记得开long long
代码
#include<iostream>
#include<string>
#include<map>
#include<set>
//#include<unordered_map>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#include<iomanip>
#include<stack>
#include<cmath>
#include<fstream>
#define X first
#define Y second
#define best 131
#define INF 0x3f3f3f3f
#define P pair<int,int>
#define ls p<<1
#define rs p<<1|1
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double eps=1e-5;
const double pai=acos(-1.0);
const int N=2e5+10;
const int maxn=1e6+10;
char s[N];
stack<int>q;
ll match[N],dp[N],cnt,ans;
int main( )
{
scanf("%s",s+1);
int len=strlen(s+1);
for(int i=1;i<=len;i++)
{
if(s[i]=='(')
{
dp[++cnt]=0;
match[cnt]=0;
q.push(cnt);
}
else if(s[i]==')')
{
if(q.size())
{
match[++cnt]=q.top();
dp[cnt]=dp[q.top()-1]+1;
q.pop();
}
else
{
dp[++cnt]=0;
match[cnt]=0;
}
ans+=dp[cnt];
}
else if(s[i]=='-')
{
ans-=dp[cnt];
while(q.size()&&q.top()>=cnt) q.pop();
if(match[cnt]) q.push(match[cnt]);
cnt--;
}
printf("%lld\n",ans);
}
return 0;
}