*[topcoder]BracketExpressions
http://community.topcoder.com/stat?c=problem_statement&pm=13243
就是能否通过把字符串中的'X'替换成"()", "[]", and "{}"来变成合法的括号字符串,
"([]X()[()]XX}[])X{{}}]"
Returns: "possible"
You can replace 'X's respectively with '{', '(', ')' and '['.
DFS搜索,Valid的判断使用stack。
#include <stack> #include <vector> #include <string> using namespace std; class BracketExpressions { public: string candidates; string ifPossible(string expression) { candidates = "()[]{}"; vector<int> xPos; for (int i = 0; i < expression.length(); i++) { if (expression[i] == 'X') { xPos.push_back(i); } } bool possible = ifPossRe(expression, 0, xPos); if (possible) return "possible"; else return "impossible"; } bool isValid(const string &expression) { stack<char> stk; for (int i = 0; i < expression.length(); i++) { if (stk.empty()) { stk.push(expression[i]); } else if (match(stk.top(), expression[i])) { stk.pop(); } else { stk.push(expression[i]); } } return stk.empty(); } bool match(char a, char b) { if (a == '(' && b == ')') return true; if (b == '(' && a == ')') return true; if (a == '[' && b == ']') return true; if (b == '[' && a == ']') return true; if (a == '{' && b == '}') return true; if (b == '{' && a == '}') return true; return false; } bool ifPossRe(string &expression, int idx, vector<int> &xPos) { if (idx == xPos.size()) { return isValid(expression); } int n = xPos[idx]; for (int i = 0; i < candidates.length(); i++) { char ch = expression[n]; expression[n] = candidates[i]; bool res = ifPossRe(expression, idx+1, xPos); expression[n] = ch; if (res) return true; } return false; } };
http://apps.topcoder.com/wiki/display/tc/SRM+628
但其实判断Backet合法的代码是错的,因为没有判断先有左括号再有右括号,以下做法更好更简洁。
bool correctBracket(string exp) { stack<char> s; // an assoicaitive array: opos[ ')' ] returns '(', opos[ ']' ] is '[', ... map<char,char> opos = { { ')', '(' }, { ']', '[' }, { '}', '{' }, }; for (char ch: exp) { // we push opening brackets to the stack if (ch == '(' || ch == '[' || ch == '{' ) { s.push(ch); } else { // If we find a closing bracket, we make sure it matches the // opening bracket in the top of the stack if (s.size() == 0 || s.top() != opos[ch]) { return false; } else { // then we remove it s.pop(); } } } // stack must be empty. return s.empty(); }
解法中还是用了基于6的幂来计算所有组合,比DFS要快。
string ifPossible(string expression) { vector<int> x; int n = expression.size(); for (int i = 0; i < n; i++) { if (expression[i] == 'X') { x.push_back(i); } } int t = x.size(); // to easily convert to base 6 we precalculate the powers of 6: int p6[6]; p6[0] = 1; for (int i = 1; i < 6; i++) { p6[i] = 6 * p6[i - 1]; } const char* CHARS = "([{)]}"; for (int m = 0; m < p6[t]; m++) { string nexp = expression; for (int i = 0; i < t; i++) { // (m / p6[i]) % 6 extracts the i-th digit of m in base 6. nexp[ x[i] ] = CHARS[ (m / p6[i]) % 6 ]; } if (correctBracket(nexp)) { return "possible"; } } return "impossible"; }