Lexicographically smallest string formed by replacing characters according to the given relation


Introduction

The task of making the lexicographically smallest string by replacing characters according to a given relation poses a captivating challenge in string control. The objective is to modify the characters inside the input string, following to the required substitution rules, in arrange to get the littlest lexicographic order. In this article, we'll focus on solving this issue utilizing C++.

We are going investigate three approaches to handle this issue, each utilizing a one of a kind technique and algorithmic method. These approaches are planned to supply distinctive bits of knowledge into understanding the issue, considering variables such as effectiveness, complexity, and ease of execution.

Approach 1: Brute Force Approach

The brute force approach includes producing all conceivable stages of the given string by supplanting characters concurring to the given connection. Ready to utilize the next_permutation work from the C++ STL to produce changes. We at that point compare each stage with the current lexicographically littlest string and overhaul it on the off chance that a little stage is found.

Algorithm

  • Step 1 − Initialize a string variable named smallest with the initial string.

  • Step 2 − Create all changes of the first string.

  • Step 3 − For each stage, emphasize the given connection and supplant characters in a like manner.

  • Step 4 − Compare the adjusted change with the current littlest string and upgrade it in case a little string is found.

  • Step 5 − Rehash steps 2-4 until all changes have been checked.

  • Step 6 − Return the ultimate littlest string.

Example

#include <iostream>
#include <algorithm>
using namespace std;

string getLexicographicallySmallest(string str, string relation) {
   string smallest = str;
   sort(relation.begin(), relation.end());
    
   do {
      string temp = str;
      for (int i = 0; i < relation.length(); i += 2) {
         replace(temp.begin(), temp.end(), relation[i], relation[i + 1]);
      }
        
      if (temp < smallest) {
         smallest = temp;
      }
   } while (next_permutation(str.begin(), str.end()));
    
   return smallest;
}
int main() {
   string str = "abccba";
   string relation = "abcxyz";
    
   string smallestString = getLexicographicallySmallest(str, relation);
    
   cout << "Lexicographically Smallest String: " << smallestString << endl;
    
   return 0;
}

Output

Lexicographically Smallest String: abccba

Approach 2: Greedy Approach

The greedy approach includes iteratively supplanting characters within the string based on the given connection. We begin from the furthest left character and check on the off chance that a little character is accessible for substitution. In case so, we supplant it and proceed with the method until no more substitutions can be made

Algorithm

  • Step 1 − Repeat through the first string from cleared out to right.

  • Step 2 − For each character, check if there's a smaller substitution character accessible within the given connection.

  • Step 3 − If a smaller character is found, supplant the current character.

  • Step 4 − Invoke getLexicographicallySmallest() function and pass its resultant value to the variable named smalleststring.

  • Step 5 − Return the adjusted string as the lexicographically littlest string.

Example

#include <iostream>
#include <algorithm>
using namespace std;

string getLexicographicallySmallest(string str, string relation) {
   sort(relation.begin(), relation.end());
    
   for (int i = 0; i < str.length(); i++) {
      for (int j = 0; j < relation.length(); j += 2) {
         if (str[i] == relation[j] && relation[j + 1] < str[i]) {
            str[i] = relation[j + 1];
         }
      }
   }
   
   return str;
}
int main() {
   string str = "abccba";
   string relation = "abcxyz";
    
   string smallestString = getLexicographicallySmallest(str, relation);
    
   cout << "Lexicographically Smallest String: " << smallestString << endl;
    
   return 0;
}

Output

Lexicographically Smallest String: abccba

Approach 3: Priority Queue Approach

The priority queue approach includes employing a priority queue to store the characters of the string in a sorted way based on the given connection. We repeat over the characters of the string and enqueue them into the priority queue. Then, we dequeue the characters from the priority queue and construct the lexicographically littlest string.

Algorithm

  • Step 1 − Initialize a priority queue to store characters in a sorted arrangement based on the given connection.

  • Step 2 − Enqueue all characters from the initial string into the priority queue.

  • Step 3 − Iterate through the characters of the first string.

  • Step 4 − For each character, dequeue the littlest character from the need line and compare it with the character from the unique string.

  • Step 5 − In case a littler substitution character is accessible within the given relation, enqueue it into the priority queue.

  • Step 6 − Repeat steps 4-5 until all characters have been prepared.

  • Step 7 − Construct the lexicographically littlest string by dequeuing all characters from the priority queue.

  • Step 8 − Turn around the string to get the right arrangement.

  • Step 9 − Return the lexicographically littlest string.

Example

#include <iostream>
#include <unordered_map>
#include <algorithm>
#include <vector>
using namespace std;

string getLexicographicallySmallest(string str, string relation) {
   vector<char> replacements(26, '#'); // Initialize replacements with a placeholder character '#'
    
   for (int i = 0; i < relation.length(); i += 2) {
      char curr = relation[i];
      char repl = relation[i + 1];
        
      if (replacements[curr - 'a'] == '#') {
         replacements[curr - 'a'] = repl;
      } else {
         replacements[curr - 'a'] = min(replacements[curr - 'a'], repl);
      }
   }
    
   for (int i = 0; i < str.length(); i++) {
      if (replacements[str[i] - 'a'] != '#' && replacements[str[i] - 'a'] < str[i]) {
         str[i] = replacements[str[i] - 'a'];
      }
   }
    
   return str;
}

int main() {
   string str = "abccba";
   string relation = "abcxyz";
    
   string smallestString = getLexicographicallySmallest(str, relation);
    
   cout << "Lexicographically Smallest String: " << smallestString << endl;
    
   return 0;
}

Output

Lexicographically Smallest String: abccba

Conclusion

In conclusion, we investigated three diverse approaches in C++ for making lexicographically negligible strings by supplanting characters agreeing to certain connections. The brute drive approach creates all stages, the eager approach iteratively replaces characters, and the need line approach employments need lines to form the littlest string. Despite the distinctive approaches, the inputs given reliably delivered the same yield "abccba" overall approaches. Each approach has focal points and may be reasonable depending on the issue imperatives and input estimate. Understanding and actualizing these approaches can successfully fathom comparative issues related to controlling strings based on certain relationships.

Updated on: 25-Aug-2023

293 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements