分类:①自身匹配的字符串,个数为self,匹配对数为self*self
②(去掉自身可匹配的()后)只剩左括号和只剩右括号的可匹配为另一类,
匹配顺序唯一,左括号再前,右括号在后
题目描述不太好理解,其实就是暴力法:从头遍历2遍,只要能匹配就算一对 但是问题在于时间复杂度太大,遂另寻它法
借鉴前人思路,看到用化简的思路,直接用string的find和erase,很妙
下面仍是用栈写的
便于理解版
#include<iostream>
#include<string>
#include<stack>
#include<cstring>
using namespace std;
stack<int>kuo;//括号栈
string ss;
int Left[300000],Right[300000];//只剩左括号、右括号的数组,记录化简后括号个数
int l_index=0,r_index=0;//数组长度
bool match(string s){//匹配函数,若本身匹配返回真;否则计算化简后括号个数
bool flag=true;
int left=0,right=0;
for(int i=0;i<s.size();i++){
if(s[i]=='(')kuo.push(i);
else if(!kuo.empty())kuo.pop();
else { //栈内无左括号来配对
right++;//剩余右括号++
flag=false;
};
}
if(!kuo.empty()){
while(!kuo.empty()){//栈内有多余左括号
left++;//剩余左括号++
kuo.pop();
}
flag=false;
}
if(left==0&&right!=0)Right[r_index++]=right;//只剩右括号的
else if(left!=0&&right==0)Left[l_index++]=left;//只剩左括号的
//左右括号都剩)(,不可能匹配
return flag;
}
int main(){
int n,self=0,answer=0;
memset(Left,0,sizeof(Left));
memset(Right,0,sizeof(Right));
scanf("%d",&n);
int k=0;
for(int i=0;i<n;i++){
cin>>ss;
if(match(ss))self++;
}
answer=answer+self*self;
for(int i=0;i<l_index;i++){
for(int j=0;j<r_index;j++){
if(Left[i]==Right[j]){//遍历左右括号数组,个数相同即配对
answer++;
}
}
}
printf("%d",answer);
return 0;
}
空间优化版
#include<iostream>
#include<string>
#include<stack>
#include<cstring>
using namespace std;
stack<int>kuo;
string ss;
int signal[300000];//记录左右括号个数差
int indexx=0;
bool match(string s){
bool flag=true;
int left=0,right=0;
for(int i=0;i<s.size();i++){
if(s[i]=='(')kuo.push(i);
else if(!kuo.empty())kuo.pop();
else {
right++;
flag=false;
};
}
if(!kuo.empty()){
while(!kuo.empty()){
left++;
kuo.pop();
}
flag=false;
}
if((left==0&&right!=0)||(left!=0&&right==0))signal[indexx++]=left-right;
//只记录满足条件的括号个数差
return flag;
}
int main(){
int n,self=0,answer=0;
memset(signal,0,sizeof(signal));
scanf("%d",&n);
int k=0;
for(int i=0;i<n;i++){
cin>>ss;
if(match(ss))self++;
}
answer=answer+self*self;
for(int i=0;i<indexx;i++){
for(int j=i+1;j<indexx;j++){//无需从头开始,因为配对顺序唯一,(在前、)在后
if(signal[i]+signal[j]==0){
answer++;
}
}
}
printf("%d",answer);
return 0;
}