Brace Expansion II

hard stack parsing set

Problem

Under a grammar, a string represents a set of lowercase words: a literal is a single-letter set, comma-separated parts inside braces form a union, and adjacent parts (juxtaposition) form a Cartesian concatenation. Return the sorted set of expanded words.

Inputexpression = "{a,b}{c,{d,e}}"
Output["ac","ad","ae","bc","bd","be"]
{a,b} = {a,b}; {c,{d,e}} = {c,d,e}; concat ⇒ all 2 × 3 pairs.

def brace_expansion_ii(expression):
    groups = [[]]            # union groups; current group is groups[-1]
    stack = []               # saved (groups) at each '{'
    i, n = 0, len(expression)
    while i < n:
        c = expression[i]
        if c == '{':
            stack.append(groups)
            groups = [[]]
        elif c == '}':
            cur = union(groups)
            groups = stack.pop()
            groups[-1] = concat(groups[-1], cur)
        elif c == ',':
            groups.append([])
        else:
            groups[-1] = concat(groups[-1], [c])
        i += 1
    return sorted(union(groups))
function braceExpansionII(expression) {
  let groups = [[]];
  const stack = [];
  for (const c of expression) {
    if (c === '{') { stack.push(groups); groups = [[]]; }
    else if (c === '}') {
      const cur = union(groups);
      groups = stack.pop();
      groups[groups.length-1] = concat(groups[groups.length-1], cur);
    } else if (c === ',') {
      groups.push([]);
    } else {
      groups[groups.length-1] = concat(groups[groups.length-1], [c]);
    }
  }
  return [...new Set(union(groups))].sort();
}
class Solution {
    public List<String> braceExpansionII(String expression) {
        Deque<List<Set<String>>> stack = new ArrayDeque<>();
        List<Set<String>> groups = new ArrayList<>();
        groups.add(new HashSet<>(Arrays.asList("")));
        for (char c : expression.toCharArray()) {
            if (c == '{') { stack.push(groups); groups = new ArrayList<>(); groups.add(new HashSet<>(Arrays.asList(""))); }
            else if (c == '}') { Set<String> cur = union(groups); groups = stack.pop(); groups.set(groups.size()-1, concat(groups.get(groups.size()-1), cur)); }
            else if (c == ',') { groups.add(new HashSet<>(Arrays.asList(""))); }
            else { groups.set(groups.size()-1, concat(groups.get(groups.size()-1), new HashSet<>(Arrays.asList(String.valueOf(c))))); }
        }
        return new ArrayList<>(new TreeSet<>(union(groups)));
    }
}
vector<string> braceExpansionII(string expression) {
    vector<vector<set<string>>> stack;
    vector<set<string>> groups = {{""}};
    for (char c : expression) {
        if (c == '{') { stack.push_back(groups); groups = {{""}}; }
        else if (c == '}') { auto cur = unionSets(groups); groups = stack.back(); stack.pop_back(); groups.back() = concat(groups.back(), cur); }
        else if (c == ',') { groups.push_back({""}); }
        else { groups.back() = concat(groups.back(), {string(1,c)}); }
    }
    auto u = unionSets(groups);
    return vector<string>(u.begin(), u.end());
}
Time: O(N · M log M) Space: O(N · M)