题意:有一个只包含'(',')','?'的字符串,'?'可以被当作'('或者')'。问这个字符串中有多少子串为合法的括号序列(即左括号和右括号可以一一配对)。
思路:由于字符串最长只有5000,可以枚举所有子串,对于相同起始位置的子串,我们从起始位置开始扫描,记一个变量sum,对于'(',sum++,对于')',sum--,对于'?'先当作')',sum--,num++。操作完成之后检查sum,若sum==0,则起始位置到当前位置为一个合法的括号序列,若<0,则判断num,若num>0,则把之前当作')'的'?'变为'(',sum+=2,num--,若num<=0,则说明之后的序列均不合法,则break。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define PI acos(-1)
#define INF 0x3f3f3f3f
#define NUM 5005
#define debug false
#define ll long long
#define lowbit(x) ((-x)&x)
#define ffor(i,d,u) for(int i=(d);i<=(u);++i)
#define _ffor(i,u,d) for(int i=(u);i>=(d);--i)
#define mst(array,Num) memset(array,Num,sizeof(array))
const int P = 1e9+7;
string s;
ll ans=0;
template <typename T>
void read(T& x)
{
x=0;
char c;T t=1;
while(((c=getchar())<'0'||c>'9')&&c!='-');
if(c=='-'){t=-1;c=getchar();}
do(x*=10)+=(c-'0');while((c=getchar())>='0'&&c<='9');
x*=t;
}
template <typename T>
void write(T x)
{
int len=0;char c[21];
if(x<0)putchar('-'),x*=(-1);
do{++len;c[len]=(x%10)+'0';}while(x/=10);
_ffor(i,len,1)putchar(c[i]);
}
void AC()
{
int len;
int num=0,sum;
cin>>s;
len = s.size()-1;
ffor(i,0,len)
{
if(s[i] == ')')continue;
sum = num = 0;
ffor(j,i,len)
{
if(s[j] == '(')++sum;
if(s[j] == ')')--sum;
if(s[j] == '?')++num,--sum;
if(sum<0)
if(num>0)sum+=2,--num;//把之前当作'('的'?'变为')'使得当前序列暂时合法
else break;
if(sum == 0)++ans;
}
}
write(ans),putchar('\n');
}
int main()
{
AC();
return 0;
}