題目描述
輸入一個長度爲n的字符串(0<=n<=20)只包含’(‘和’)’。對於這個字符串如”(())”,”()()”是匹配的,”)(“,”())(“都不是括號匹配的。
刪除最左邊的’(‘,從剩下的字符串中刪除任意的’)’,使得刪除後的字符串仍然是括號匹配的。
對整個字符串重複該刪除操作,直到刪除了整個字符串。問這樣的括號匹配方案有多少個?(只要有一次刪除的右括號’)’不同則認爲是一個不同的方案)
樣例
輸入 (((())))
輸出 24輸入 ()()()
輸出 1
思路
由於字符串長度最大隻有20,可以考慮使用暴力枚舉,遞歸處理。
答案
#include <iostream>
#include <string>
using namespace std;
int count(string str, int len, int left) {
// cout << str << " " << left << endl;
if(len<left || len<=0 || left<0) return 0;
if(left==0) return 1;
int ret=0, i=0;
// 找到目前字符串的最左左括號位置並刪除
for(; i<len; i++){
if(str[i] == '('){
str[i] = '-';
break;
}
// 假如字符串的首位出現右括號表示之前的刪除操作出現不合法
// 則該方案不可行
if(str[i] == ')') return 0;
}
// 枚舉剩下的右括號刪除後是否合法
int change = -1;
for(int j=i+1; j<len; j++) {
if(change==-1 && str[j]==')'){
str[j] = '-';
change = j;
ret += count(str, len, left-2);
}
if(change != -1){
str[change] = ')';
change = -1;
}
}
return ret;
}
int main(){
string str;
cin >> str; // "(", ")", "-"表示刪除
int len = str.length();
bool illegal = false;
for(int i=0; i<len; i++){
if(str[i]!='(' && str[i] != ')'){
cout << "輸入不合法!" << endl;
illegal = true;
break;
}
}
if(!illegal)
cout << count(str, len, len) << endl;
return 0;
}
思路擴展
這種匹配的題目常常與卡特蘭數扯上關係,比如輸入括號對數n,輸出匹配方案數。