Generate all possible strings formed by replacing letters with given respective symbols


Generating all possible strings is to replace a character of a string with a respective symbol and produce all possible strings. We will be given a string ‘s’ of size ‘N’ and an unordered map ‘mp’ of a pair of characters of size ‘M’. Here we can replace the mp[i][0] with mp[i][1] in the string ‘s’ and by doing this our task is to generate all possible strings.

Sample Examples

Input: s = “xyZ”, mp = {‘x’ : ‘$’, ‘y’ : ‘#’, ‘Z’ : ‘^’}
Output: 
xyZ
xy^
x#Z
z#^
$yZ
$y^
$#Z
$#^

Explanation − In the above example, there are a total 8 strings generated.

Input: s = “pQ”, mp = {‘p’ : ‘#’, ‘Q’ : ‘$’}
Output:
pQ
#Q
p$
#$

Explanation − In the above example, there are a total of 4 strings generated.

Input: s = “w”, mp = {‘w’ : ‘#’}
Output:
w
#

Explanation − In the above example, there are a total of 2 strings generated.

Approach

In this approach, we will use the concept of brute force to find all the combinations which are possible.

  • First, we will create a function that will take a string, current index, and the given map as the parameters and return type will be void.

  • In the function, we will define the base condition in which the current index is equal to the size of the string, then we will print that string and return from the function.

  • Otherwise, we will have two choices one is to don’t change the current index and move to the next which will always be an option.

  • The second choice is only possible if the current character has any replacement. If the replacement exists then we will call to the replacement.

  • After that we will return from the function and it will automatically produce all the required results.

Let’s discuss the code of the above approach for better understanding.

Example

#include <bits/stdc++.h>
using namespace std;
// Function to generate all possible strings by replacing the characters with paired symbols
void possibleStrings(string str, int idx, unordered_map<char, char> mp){
   if (idx == str.size()) {
      cout << str << endl;
      return;
   }
   // Function call with the idx-th character not replaced
   possibleStrings(str, idx + 1, mp);
   // Replace the idx-th character
   str[idx] = mp[str[idx]];
   // Function call with the idx-th character replaced
   possibleStrings(str, idx + 1, mp);
   return;
}
int main(){
   string str = "xyZ";
   unordered_map<char, char> mp;
   mp['x'] = '$';
   mp['y'] = '#';
   mp['Z'] = '^';
   mp['q'] = '&';
   mp['2'] = '*';
   mp['1'] = '!';
   mp['R'] = '@';
   int idx = 0;
   // Call 'possibleStrings' function to generate all possible strings
   //Here in the 'possible strings' function, we have passed string 'str', index 'idx', and map 'mp'
   possibleStrings(str, idx, mp);
   return 0;
}

Output

xyZ
xy^
x#Z
x#^
$yZ
$y^
$#Z
$#^

Time and Space Complexity

The time complexity of the above code is O(N*2^N) because we have just back traversed over the N elements and Where N is the size of the string ‘s’.

The space complexity of the above code is O(N*N), as we are sending the string as complete and there could be N copies of the string that exists at the same time.

Back Tracking

In the previous approach, we were sending the string without the pointer which leads to taking a lot of space. To reduce the space and time complexity we will use the concept of the backtracking.

Example

#include <bits/stdc++.h>
using namespace std;
// Function to generate all possible strings by replacing the characters with paired symbols
void possibleStrings(string& str, int idx, unordered_map<char, char> mp){
   if (idx == str.size()) {
      cout << str << endl;
      return;
   }
   // Function call with the idx-th character not replaced
   possibleStrings(str, idx + 1, mp);
   // storing the current element 
   char temp = str[idx];
   // Replace the idx-th character
   str[idx] = mp[str[idx]];
   // Function call with the idx-th character replaced
   possibleStrings(str, idx + 1, mp);
   // backtracking 
   str[idx] = temp;
   return;
}
int main(){
   string str = "xyZ";
   unordered_map<char, char> mp;
   mp['x'] = '$';
   mp['y'] = '#';
   mp['Z'] = '^';
   mp['q'] = '&';
   mp['2'] = '*';
   mp['1'] = '!';
   mp['R'] = '@';
   int idx = 0;
   // Call 'possibleStrings' function to generate all possible strings
   //Here in the 'possible strings' function, we have passed string 'str', index 'idx', and map 'mp'
   possibleStrings(str, idx, mp);
   return 0;
}

Output

xyZ
xy^
x#Z
x#^
$yZ
$y^
$#Z
$#^

Time and Space Complexity

The time complexity of the above code is O(N*2^N) because we have just back traversed over the N elements and Where N is the size of the string ‘s’.

The space complexity of the above code is O(N), as we are sending the address of the string makes only maximum N stacks going down.

Conclusion

In this tutorial, we have implemented a program to generate all possible strings formed by replacing letters with given respective symbols. Here we have seen the backtracking approach and the time complexity of the code is O(N*2^N), where N is the size of the string, and space complexity is the same as the time complexity. To reduce the space complexity, we have implemented the backtracking process.

Updated on: 16-May-2023

146 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements