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.
with k >= 2, we have R({e_1,e_2,...}) = R(e_1) ∪ R(e_2) ∪ ...
For expressions e_1and 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 expressionrepresenting a set of words under the given grammar, return the sorted list of words that the expression represents.
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 expressionrepresents a set of words based on the grammar given in the description.
Thoughts:
for level larger than 1, recursively reduce level of braces down by 1.
for level == 0, if there is "," , then initialize a new group by appending a [] to the groups.
Finally, for each group, calculate the cartesian product and then join it with other groups, and then filter redundant elements and sort the filtered elements.
state 0: deal with a single string
state 1: deal with a set with the form {x}. x can be valid expression
state 2: deal with union of sets: {a, b, c, d}.
state 3: deal with cartesian product of sets: {abcd}
Relationship:
state 1 is { state 2 }
state 2 is from *state 3, separated by ","
state 3 is from combination of state 0 and state 1
Recursion with simplified 2 state graph: 1. union: a,b
cartesian product: abcd
Code:
class Solution:
def braceExpansionII(self, expression: str) -> List[str]:
groups = [[]]
level = 0
for i, c in enumerate(expression):
if c == '{':
if level == 0:
start = i + 1
level += 1
elif c == '}':
level -= 1
if level == 0:
groups[-1].append(self.braceExpansionII(expression[start:i]))
elif level == 0:
if c == ',':
groups += [[]]
else:
groups[-1].append(c)
words = set()
for group in groups:
words |= set(map(''.join, itertools.product(*group)))
return sorted(words)