题目描述
输入一个长度为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,输出匹配方案数。