-
Notifications
You must be signed in to change notification settings - Fork 106
/
brace-expansion.cpp
59 lines (55 loc) · 1.98 KB
/
brace-expansion.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// Time: O(p*l * log(p*l)), p is the production of all number of options
// , l is the length of a word
// Space: O(p*l)
class Solution {
public:
vector<string> expand(string S) { // nested is fine
int i = 0;
return generateWords(S, &i);
}
private:
vector<string> generateWords(const string& expr, int *i) {
vector<vector<string>> options;
while (*i != expr.length() &&
string(",}").find(expr[*i]) == string::npos) {
vector<string> tmp;
if (string("{,}").find(expr[*i]) == string::npos) {
tmp.emplace_back(string(1, expr[*i]));
++(*i); // a-z
} else if (expr[*i] == '{') {
tmp = generateOption(expr, i);
}
options.emplace_back(move(tmp));
}
return formWords(options);
}
vector<string> generateOption(const string& expr, int *i) {
set<string> option_set;
while (*i != expr.length() && expr[*i] != '}') {
++(*i); // { or ,
for (const auto& option : generateWords(expr, i)) {
option_set.emplace(option);
}
}
++(*i); // }
return vector<string>(option_set.cbegin(), option_set.cend());
}
vector<string> formWords(const vector<vector<string>>& options) {
set<string> words_set;
int total = 1;
for (const auto& opt : options) {
total *= opt.size();
}
for (int i = 0; i < total; ++i) {
vector<string> tmp;
int curr = i;
for (int j = options.size() - 1; j >= 0; --j) {
tmp.emplace_back(options[j][curr % options[j].size()]);
curr /= options[j].size();
}
reverse(tmp.begin(), tmp.end());
words_set.emplace(accumulate(tmp.cbegin(), tmp.cend(), string()));
}
return vector<string>(words_set.cbegin(), words_set.cend());
}
};