1096. Brace Expansion II
https://leetcode.com/problems/brace-expansion-ii/
eval针对集合的表达式,括号内代表一个完整的子表达式,","代表并,没有","隔离则代表拼接。这题和Basic Caculator III 思路是一致的,区别在于这里的基本操作数不是数字,而是字符串集合;+替换成了并操作,*成了字符串拼接。除了可以用递归做外,依然可以维持两个栈分别存操作数和操作符。当遇到{时操作符压栈,}时递归处理直到遇到{;*则一直压栈直到遇到+开始处理前面的*。 字符串拼接没有特定的操作符表示,有好几个coner case需要注意。
/*
* @lc app=leetcode id=1096 lang=cpp
*
* [1096] Brace Expansion II
*
* https://leetcode.com/problems/brace-expansion-ii/description/
*
* algorithms
* Hard (56.14%)
* Likes: 81
* Dislikes: 60
* Total Accepted: 3.9K
* Total Submissions: 6.8K
* Testcase Example: '"{a,b}{c,{d,e}}"\r'
*
* Under a grammar given below, strings can represent a set of lowercase
* words. Let's use R(expr) to denote the set of words the expression
* represents.
*
* Grammar can best be understood through simple examples:
*
*
* Single letters represent a singleton set containing that word.
*
* R("a") = {"a"}
* R("w") = {"w"}
*
*
* When we take a comma delimited list of 2 or more expressions, we take the
* union of possibilities.
*
* R("{a,b,c}") = {"a","b","c"}
* R("{{a,b},{b,c}}") = {"a","b","c"} (notice the final set only contains each
* word at most once)
*
*
* When we concatenate two expressions, we take the set of possible
* concatenations between two words where the first word comes from the first
* expression and the second word comes from the second
* expression.
*
* R("{a,b}{c,d}") = {"ac","ad","bc","bd"}
* R("a{b,c}{d,e}f{g,h}") = {"abdfg", "abdfh", "abefg", "abefh", "acdfg",
* "acdfh", "acefg", "acefh"}
*
*
*
*
* Formally, the 3 rules for our grammar:
*
*
* For every lowercase letter x, we have R(x) = {x}
* For expressions e_1, e_2, ... , e_k with k >= 2, we have R({e_1,e_2,...}) =
* R(e_1) ∪ R(e_2) ∪ ...
* For expressions e_1 and e_2, we have R(e_1 + e_2) = {a + b for (a, b) in
* R(e_1) × R(e_2)}, where + denotes concatenation, and × denotes the cartesian
* product.
*
*
* Given an expression representing a set of words under the given grammar,
* return the sorted list of words that the expression represents.
*
*
*
*
* Example 1:
*
*
* Input: "{a,b}{c,{d,e}}"
* Output: ["ac","ad","ae","bc","bd","be"]
*
*
*
* Example 2:
*
*
* Input: "{{a,z},a{b,c},{ab,z}}"
* Output: ["a","ab","ac","z"]
* Explanation: Each distinct word is written only once in the final
* answer.
*
*
*
*
* Constraints:
*
*
* 1 <= expression.length <= 50
* expression[i] consists of '{', '}', ','or lowercase English letters.
* The given expression represents a set of words based on the grammar given in
* the description.
*
*
*
*/
class Solution {
public:
vector<string> braceExpansionII(string expression) {
const int N = expression.size();
stack<set<string>> s;
stack<char> ops;
string cur;
set<string> cur_set;
const auto add = [](set<string> &l1, set<string> &l2) {
set<string> r;
r.insert(l1.begin(), l1.end());
r.insert(l2.begin(), l2.end());
return r;
};
const auto mult = [](set<string> &l1, set<string> &l2) {
set<string> r;
for (const auto s1 : l1) {
for (const auto s2 : l2) {
r.insert(s1 + s2);
}
}
return r;
};
const auto operation = [&](char op, set<string> &a, set<string> &b) {
switch (op)
{
case ',':
s.push(add(a, b));
break;
case '*':
s.push(mult(a, b));
break;
default:
break;
}
};
for (int i = 0; i < N; ++i) {
const auto c = expression[i];
if (c >= 'a' && c <= 'z') {
cur.push_back(c);
if (!(expression[i + 1] >= 'a' && expression[i + 1] <= 'z')) {
cur_set.insert(cur);
s.push(set<string>(cur_set));
cur_set.clear();
cur.clear();
}
} else if (c == '{') {
if (i > 0 && expression[i - 1] != ',' && expression[i - 1] != '{' && expression[i - 1] != '}') ops.push('*');
ops.push(c);
} else if (c == '}') {
while (ops.top() != '{') {
const auto op = ops.top(); ops.pop();
auto sec = s.top(); s.pop();
auto first = s.top(); s.pop();
operation(op, first, sec);
}
ops.pop();
if (i < N - 1 && expression[i + 1] != ',' && expression[i + 1] != '}') ops.push('*');
} else {
while (!ops.empty() && ops.top() == '*' && c == ',') {
auto sec = s.top(); s.pop();
auto first = s.top(); s.pop();
operation(ops.top(), first, sec);
ops.pop();
}
ops.push(c);
}
}
while (s.size() > 1) {
auto sec = s.top(); s.pop();
auto first = s.top(); s.pop();
operation(ops.top(), first, sec);
ops.pop();
}
return vector<string>(s.top().begin(), s.top().end());
}
};
Last updated
Was this helpful?