題目描述:
/**
一般的括號匹配問題是這樣的:
給出一個字符串祠汇,判斷這個括號匹配是不是合法的括號匹配。
如"((" 和 "())"都不是合法的括號匹配熄诡,但是"()()()"可很,"(()())()"等就是合法的括號匹配。
這個問題解決起來非常簡單粮彤,相信大家都知道怎么解決根穷。
現(xiàn)在給出一個加強版的括號匹配問題:
給出n個由括號 '(' 和 ‘)’ 組成的字符串,
請計算出這些字符串中有多少對字符串滿足si + sj是合法的括號匹配导坟。
如果si + sj和sj + si都是合法的括號匹配(i ≠ j)屿良,
那么這兩種搭配都需要計入答案;
如果對于si惫周,si + si是合法的括號匹配尘惧,那么也需要計入答案。
輸入描述:
第一行是一個整數(shù)n递递,表示字符串的個數(shù)喷橙;
接下來n行是n個非空字符串,全部由'('和')'組成登舞。
1 <= n <= 3 * 105贰逾,字符串的長度之和不超過3 * 105。
輸出描述:
一個整數(shù)菠秒,表示滿足條件的字符串對的數(shù)量疙剑。
輸入例子1:
3
()
(
)
輸出例子1:
2
輸入例子2:
5
(()
)))))
()()()
(((
))
輸出例子2:
1
*/
思路如下:
記錄leftBracketNum rightBracketNum 多余的括號數(shù)
要匹配的上才行(兩個指針的增添過程類似判斷合法性的過程)
然后用一個map記錄上來即可,兩個都多余的情況肯定不可能有人和其匹配,都為0可以左右匹配言缤,具體看代碼
代碼如下:
#include<stdio.h>
#include<iostream>
#include<string>
#include<map>
#define MAX_N 300000
typedef long long LL;
using namespace std;
string strs[MAX_N];
int main()
{
int N;
map<int, int> cntMap;
cin>>N;
for(int i=0; i<N; i++){
cin>>strs[i];
int leftBracketNum=0, rightBracketNum=0;
for(int j=0; strs[i][j]!='\0'; j++){
if(strs[i][j]!='(' && strs[i][j]!=')')
return -1;
if(strs[i][j]=='('){
leftBracketNum++;
}
else if(strs[i][j]==')'){
if(leftBracketNum>0)
leftBracketNum--;
else
rightBracketNum++;
}
}
//leftBracketNum rightBracketNum保證>=0
if(leftBracketNum && rightBracketNum){
continue;
}
//leftBracketNum rightBracketNum兩個均為0
if(!leftBracketNum && !rightBracketNum){
if(cntMap.find(0)==cntMap.end())
cntMap[0]=1;
else
cntMap[0]++;
continue;
}
//leftBracketNum rightBracketNum只有一個為0
if(leftBracketNum){
if(cntMap.find(leftBracketNum)==cntMap.end())
cntMap[leftBracketNum]=1;
else
cntMap[leftBracketNum]++;
}
else if(rightBracketNum){
//這里用負數(shù)表示
if(cntMap.find(-rightBracketNum)==cntMap.end())
cntMap[-rightBracketNum]=1;
else
cntMap[-rightBracketNum]++;
}
}
LL total=0;
for(map<int, int>::iterator it=cntMap.begin(); it!=cntMap.end(); it++){
if(it->first<0)
continue;
else if(it->first==0){//計算自身就是合法的情形
total+=((LL)(it->second)*(it->second));
//cout<<"first=0"<<" "<<"second="<<it->second<<endl;
}
else{
if(cntMap.find(-it->first)!=cntMap.end()){//計算左右可以匹配的情形
total+=(it->second)*cntMap[-it->first];
//cout<<"first="<<it->first<<" "<<"left_second="<<it->second<<" "<<"right_second="<<cntMap[-it->first]<<endl;
}
}
}
cout<<total<<endl;
return 0;
}