Given a string R(x) of length n representing an expression having the set of words under the given grammar:
- For every lowercase letter x, R(x) = {x}
- For expressions e_1, e_2, …, e_k with k≥2, R({e_1, e_2, …, e_k}) = R(e_1) ∪ R(e_2) ∪ … ∪ R(e_k).
- For expressions e_1 and e_2, 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.
The task is to find the sorted list of words that the expression represents.
Examples:
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.
{a, z}, a{b, c}, {ab, z} → {a, z}, {ab, ac}, {ab, z} → [a, z, ab, ac]Input: “{a, b}{c, {d, e}}”
Output: [“ac”, “ad”, “ae”, “bc”, “bd”, “be”]
Approach: From the given grammar, strings can represent a set of lowercase words. Let R(expr) denote the set of words represented by the expression. Consider the following examples to understand the approach.
- Single letters represent a singleton set containing that word.
- If a comma-delimited list of 2 or more expressions is encountered, take the union of possibilities.
- While concatenating two expressions, 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”) = {“a”}
R(“w”) = {“w”}
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)
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”}
Follow the steps below to solve the problem:
- Iterate over the characters of the string and check the following three conditions:
- If {…} is encountered, get the result inside {…} by recursively calling the function and do the Cartesian product with the current set of strings with the returned set of strings.
- If a comma(, ) is encountered, push the current set of strings to the result and empty the current strings.
- If a letter is encountered, do the Cartesian product with the current set of strings.
- Finally, sort all the strings in the result set and print only unique strings.
Below is the implementation of the above approach:
C++
// C++ program to implement the above approach #include <bits/stdc++.h> using namespace std; // Function to get the Cartesian product // of two set of strings vector<string> getProduct(vector<string>& lhs, vector<string>& rhs) { // If lhs is empty, // return rhs if (lhs.empty()) return rhs; // Store the Cartesian product // of two set of strings vector<string> ret; // Iterate over characters of both // strings and insert Cartesian product for ( auto sl : lhs) for ( auto sr : rhs) ret.push_back(sl + sr); return ret; } // Function to find the sorted list of words // that the expression represents vector<string> braceExpansion(string expression) { // Store the sorted list of words // that the expression represents vector<string> ret; // Store the current set of strings vector<string> cur; // Append Comma expression += ', ' ; // Stores the length of expression int len = expression.size(); // Iterate over the characters // of the string(expression) for ( int i = 0; i < len; ++i) { // Stores the current character char c = expression[i]; // If { is encountered, find // its closing bracket, } if (c == '{' ) { // Store the characters inside // of these brackets string sub; // Stores count of unbalanced '{'' int cnt = 1; // Iterate over characters of // expression after index i while (++i < len) { // If current character is '{' if (expression[i] == '{' ) { // Update cnt ++cnt; } // If current character is '}' else if (expression[i] == '}' ) { // Update cnt --cnt; } // If cnt is equal to 0 if (cnt == 0) break ; // Append current character sub += expression[i]; } // Recursively call the function // for the string, sub vector<string> sub_ret = braceExpansion(sub); // Store the cartesian product of cur // and sub_ret in cur cur = getProduct(cur, sub_ret); } // If current character is Comma else if (c == ', ' ) { // Push cur result into ret ret.insert(begin(ret), begin(cur), end(cur)); // Clear the current set // of strings cur.clear(); } else { // Append the current character to tmp vector<string> tmp(1, string(1, c)); // Store the cartesian product of // tmp and cur in cur cur = getProduct(cur, tmp); } } // Sort the strings present in ret // and get only the unique set of strings sort(begin(ret), end(ret)); auto iter = unique(begin(ret), end(ret)); ret.resize(distance(begin(ret), iter)); return ret; } // Driver Code int main() { // Given expression, str string str = "{a, b}{c, {d, e}}" ; // Store the sorted list of words vector<string> res; // Function Call res = braceExpansion(str); // Print the sorted list of words for (string x : res) { cout << x << " " ; } return 0; } |
ac ad ae bc bd be
Time Complexity: O(N2)
Auxiliary Space: O(N)
Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.