题意是给一个仅有’(‘,’)’,’?’的字符串,问有多少个子串是美丽的。一个字符串是美丽的当且仅当能替换’?’为’(‘或’)’使得替换后的字符串非空且括号匹配。
先考虑检测一个字符串是否美丽的情况:
从左向右遍历串,
设置变量
qmark
q
m
a
r
k
和
score
s
c
o
r
e
。
1. 遇到 (
时
score:=score+1
s
c
o
r
e
:=
s
c
o
r
e
+
1
,遇到 )
时
score:=score−1
s
c
o
r
e
:=
s
c
o
r
e
−
1
。
如果没有 ?
的话,只用操作1,遍历的任何时刻
score≥0
s
c
o
r
e
≥
0
且到最后
score=0
s
c
o
r
e
=
0
的话代表括号匹配。此时
score
s
c
o
r
e
可以代表栈的大小(如果用栈解括号匹配问题的话)。
2. 遇到 ?
时,如果
qmark>score
q
m
a
r
k
>
s
c
o
r
e
,则必须将其中的一个 ?
号变为 (
从而使得
qmark:=qmark−1,score:=score+1
q
m
a
r
k
:=
q
m
a
r
k
−
1
,
s
c
o
r
e
:=
s
c
o
r
e
+
1
,否则如果之前的 ?
都变为 )
的话,之前的部分肯定不匹配。
操作2使得遍历的任何时刻
qmark≤score
q
m
a
r
k
≤
s
c
o
r
e
。
3. 最后
qmark≥score
q
m
a
r
k
≥
s
c
o
r
e
的话说明该字符串美丽,因为可以用 )
匹配掉所有的 (
。
#include <bits/stdc++.h>
using namespace std;
int score,qmark;
void update(char ch)
{
if(ch=='(') ++score;
if(ch==')') --score;
if(ch=='?') ++qmark;
}
int main()
{
ios::sync_with_stdio(false);
string s;
int ans = 0;
cin >>s;
for(int i=0;i<s.length();++i)
{
score=qmark=0;
for(int j=0;i+j<s.length();++j)
{
update(s[i+j]);
if(qmark && qmark > score) --qmark,++score;
if(score<0) break;
if(j%2&&qmark>=score) ++ans;
}
}
cout <<ans << '\n';
return 0;
}