GeeksforGeeks App
Open App
Browser
Continue

# Lexicographically smallest and largest string possible via Transitive mapping

Given two strings str1 and str2 containing lowercase letters. The task is to convert the given string str3 into lexicographically smallest and largest string that can be formed under the following conditions:

• The alphabet at the same indices in strings str1 and str2 are equivalent to each other.
• Equivalence follows the transitivity rule. meaning if x is equivalent to y and y is equivalent to z then x is equivalent to z.
• Every character is equivalent to itself.

Examples:

Input: str1 = “abc”, str2 = “xyz”, str3 = “yzp”
Output: bcp yzp
Explanation: a, b, and c are equivalent to x, y and z respectively and vice-versa.
So the smallest string can be possible after replacing y with b and z with c.
There is no mapping found for p hence it is unchanged.
Similarly, biggest string possible will be “yzp”.

Input: str1 = “geeksgeeks”, str2 = “dedication”, str3 = “truegeek”
Output: aruaaaaa truttttt
Explanation: Above deduction can be implemented to find “aruaaaaa”
and “truttttt” as the lexicographic smallest and biggest string.

Approach: To solve the problem follow the below observations:

Observations:

• Since we know that the characters having direct or indirect connections with each other have to be in the group hence it can be solved using disjoint set data structures
• After the set is formed, we just have to check whether a character in the input string and an arbitrary character from ‘a’ to ‘z’ (for lexicographic smallest) and ‘z’ to ‘a’ (for lexicographic biggest) matches with it or not.

Follow the given steps to solve the problem:

• Implement a disjoint set data structure of size 26 as obj.
• If the lengths of str1 and str2 are not equal print “All characters not mapped”.
• Traverse str1 & str2 and perform union on its characters with each other.
• Traverse str3:
• For each character find the lexicographically smallest character to which it is mapped and the largest character to which it is mapped.
• Concatenate those characters into their respective strings.
• Store the result in a pair and return it as the final answer.

Below is the implementation for the above approach:

## C++14

 `// C++ code to implement the approach` `#include ``using` `namespace` `std;` `// Class to utilize disjoint set union.``class` `DisjSet {``    ``int` `*rank, *parent, n;` `public``:``    ``// Constructor to create and``    ``// initialize sets of n items``    ``DisjSet(``int` `n)``    ``{``        ``rank = ``new` `int``[n];``        ``parent = ``new` `int``[n];``        ``this``->n = n;``        ``makeSet();``    ``}` `    ``// Creates n single item sets``    ``void` `makeSet()``    ``{``        ``for` `(``int` `i = 0; i < n; i++) {``            ``parent[i] = i;``        ``}``    ``}` `    ``// Finds set of given item x``    ``int` `find(``int` `x)``    ``{``        ``// Finds the representative of``        ``// the set that x is an element of``        ``if` `(parent[x] != x) {` `            ``// If x is not the parent of``            ``// itself, then x is not the``            ``// representative of it's set,``            ``parent[x] = find(parent[x]);` `            ``// So we recursively Find its``            ``// parent and move i's node``            ``// directly under the``            ``// representative of this set``        ``}` `        ``return` `parent[x];``    ``}` `    ``// Do union of two sets represented``    ``// by x and y.``    ``void` `Union(``int` `x, ``int` `y)``    ``{` `        ``// Find current sets of x and y``        ``int` `xset = find(x);``        ``int` `yset = find(y);` `        ``// If they are already in same set``        ``if` `(xset == yset)``            ``return``;` `        ``// Put smaller ranked item under``        ``// bigger ranked item if ranks are``        ``// different``        ``if` `(rank[xset] < rank[yset]) {``            ``parent[xset] = yset;``        ``}``        ``else` `if` `(rank[xset] > rank[yset]) {``            ``parent[yset] = xset;``        ``}` `        ``// If ranks are same, then``        ``// increment rank.``        ``else` `{``            ``parent[yset] = xset;``            ``rank[xset] = rank[xset] + 1;``        ``}``    ``}``};` `// Function to find the lexicographically``// smallest and largest string``pair printTransitive(string& str1,``                                     ``string& str2,``                                     ``string& str3)``{``    ``DisjSet obj(26);``    ``pair ans;` `    ``if` `(str1.length() != str2.length())``        ``return` `{ ``"All characters"``, ``"not mapped"` `};` `    ``for` `(``int` `i = 0; i < str1.length(); i++)``        ``obj.Union(str1[i] - 97, str2[i] - 97);` `    ``// Loop to find the lexicographically smallest``    ``// and largest mapping for each character``    ``for` `(``int` `i = 0; i < str3.length(); i++) {``        ``for` `(``char` `j = ``'a'``; j <= ``'z'``; j++) {``            ``if` `(obj.find(str3[i] - 97)``                ``== obj.find(j - 97)) {``                ``ans.first.push_back(j);``                ``break``;``            ``}``        ``}``        ``for` `(``char` `j = ``'z'``; j >= ``'a'``; j--) {``            ``if` `(obj.find(str3[i] - 97)``                ``== obj.find(j - 97)) {``                ``ans.second.push_back(j);``                ``break``;``            ``}``        ``}``    ``}` `    ``// Return the pair of string``    ``return` `ans;``}` `// Driver code``int` `main()``{``    ``string str1 = ``"geeksgeeks"``, str2 = ``"dedication"``;``    ``string str3 = ``"truegeek"``;` `    ``// Function call``    ``pair result``        ``= printTransitive(str1, str2, str3);``    ``cout << result.first << ``" "` `<< result.second;``    ``return` `0;``}`

## Java

 `// Java code to implement the approach``import` `java.util.*;` `class` `Main``{` `  ``// Class to utilize disjoint set union.``  ``static` `class` `DisjSet {``    ``int``[] rank, parent;``    ``int` `n;` `    ``// Constructor to create and``    ``// initialize sets of n items``    ``public` `DisjSet(``int` `n)``    ``{``      ``rank = ``new` `int``[n];``      ``parent = ``new` `int``[n];``      ``this``.n = n;``      ``makeSet();``    ``}` `    ``// Creates n single item sets``    ``void` `makeSet()``    ``{``      ``for` `(``int` `i = ``0``; i < n; i++) {``        ``parent[i] = i;``      ``}``    ``}` `    ``// Finds set of given item x``    ``int` `find(``int` `x)``    ``{``      ``// Finds the representative of``      ``// the set that x is an element of``      ``if` `(parent[x] != x) {` `        ``// If x is not the parent of``        ``// itself, then x is not the``        ``// representative of it's set,``        ``parent[x] = find(parent[x]);` `        ``// So we recursively Find its``        ``// parent and move i's node``        ``// directly under the``        ``// representative of this set``      ``}` `      ``return` `parent[x];``    ``}` `    ``// Do union of two sets represented``    ``// by x and y``    ``void` `Union(``int` `x, ``int` `y)``    ``{``      ``// Find current sets of x and y``      ``int` `xset = find(x);``      ``int` `yset = find(y);` `      ``// If they are already in same set``      ``if` `(xset == yset)``        ``return``;` `      ``// Put smaller ranked item under``      ``// bigger ranked item if ranks are``      ``// different``      ``if` `(rank[xset] < rank[yset]) {``        ``parent[xset] = yset;``      ``}``      ``else` `if` `(rank[xset] > rank[yset]) {``        ``parent[yset] = xset;``      ``}` `      ``// If ranks are same, then``      ``// increment rank.``      ``else` `{``        ``parent[yset] = xset;``        ``rank[xset] = rank[xset] + ``1``;``      ``}``    ``}``  ``}``  ``// Function to find the lexicographically``  ``// smallest and largest string``  ``public` `static` `List >``    ``printTransitive(String str1, String str2, String str3)``  ``{``    ``DisjSet obj = ``new` `DisjSet(``26``);``    ``List > ans = ``new` `ArrayList<>();` `    ``if` `(str1.length() != str2.length()) {``      ``List temp = ``new` `ArrayList<>();``      ``temp.add(``"All characters"``);``      ``temp.add(``"not mapped"``);``      ``ans.add(temp);``      ``return` `ans;``    ``}` `    ``List temp = ``new` `ArrayList<>();``    ``temp.add(``""``);``    ``temp.add(``""``);``    ``ans.add(temp);` `    ``for` `(``int` `i = ``0``; i < str1.length(); i++)``      ``obj.Union(str1.charAt(i) - ``97``,``                ``str2.charAt(i) - ``97``);` `    ``// Loop to find the lexicographically smallest and``    ``// largest mapping for each character``    ``for` `(``int` `i = ``0``; i < str3.length(); i++) {``      ``for` `(``char` `j = ``'a'``; j <= ``'z'``; j++) {``        ``if` `(obj.find(str3.charAt(i) - ``97``)``            ``== obj.find(j - ``97``)) {``          ``String st = ans.get(``0``).get(``0``);``          ``ans.get(``0``).set(``0``, st + j);``          ``break``;``        ``}``      ``}``      ``for` `(``char` `j = ``'z'``; j >= ``'a'``; j--) {``        ``if` `(obj.find(str3.charAt(i) - ``97``)``            ``== obj.find(j - ``97``)) {``          ``String st = ans.get(``0``).get(``1``);``          ``ans.get(``0``).set(``1``, st + j);``          ``break``;``        ``}``      ``}``    ``}``    ``// Return the pair of string``    ``return` `ans;``  ``}` `  ``// Driver Code``  ``public` `static` `void` `main(String[] args)``  ``{``    ``String str1 = ``"geeksgeeks"``, str2 = ``"dedication"``;``    ``String str3 = ``"truegeek"``;` `    ``// Function Call``    ``List > result``      ``= printTransitive(str1, str2, str3);``    ``System.out.println(result.get(``0``).get(``0``) + ``" "``                       ``+ result.get(``0``).get(``1``));``  ``}``}` `// This code is contributed by Tapesh (tapeshdua420)`

## Python3

 `# Python code to implement the approach` `# Class to utilize disjoint set union.``class` `DisjSet:``    ``def` `__init__(``self``, n):``        ``self``.rank ``=` `[``0``] ``*` `n``        ``self``.parent ``=` `[``0``] ``*` `n``        ``self``.n ``=` `n``        ``self``.makeSet()` `    ``# Creates n single item sets``    ``def` `makeSet(``self``):``        ``for` `i ``in` `range``(``self``.n):``            ``self``.parent[i] ``=` `i` `    ``# Finds set of given item x``    ``def` `find(``self``, x):``        ``# Finds the representative of the set that x is an element of``        ``if` `self``.parent[x] !``=` `x:` `            ``# If x is not the parent of``            ``# itself, then x is not the``            ``# representative of it's set,``            ``self``.parent[x] ``=` `self``.find(``self``.parent[x])``            ``# So we recursively Find its``            ``# parent and move i's node``            ``# directly under the``            ``# representative of this set``        ``return` `self``.parent[x]` `    ``# Do union of two sets represented``    ``# by x and y``    ``def` `Union(``self``, x, y):``        ``# Find current sets of x and y``        ``xset ``=` `self``.find(x)``        ``yset ``=` `self``.find(y)` `        ``# If they are already in same set``        ``if` `xset ``=``=` `yset:``            ``return` `          ``# Put smaller ranked item under``          ``# bigger ranked item if ranks are``          ``# different``        ``if` `self``.rank[xset] < ``self``.rank[yset]:``            ``self``.parent[xset] ``=` `yset` `        ``elif` `self``.rank[xset] > ``self``.rank[yset]:``            ``self``.parent[yset] ``=` `xset``          ``# If ranks are same, then``        ``# increment rank.``        ``else``:``            ``self``.parent[yset] ``=` `xset``            ``self``.rank[xset] ``+``=` `1` `  ``# Function to find the lexicographically``  ``# smallest and largest string`  `def` `printTransitive(str1, str2, str3):``    ``obj ``=` `DisjSet(``26``)``    ``ans ``=` `[]` `    ``if` `len``(str1) !``=` `len``(str2):``        ``temp ``=` `[``"All characters"``, ``"not mapped"``]``        ``ans.append(temp)``        ``return` `ans` `    ``temp ``=` `[""] ``*` `2``    ``ans.append(temp)` `    ``for` `i ``in` `range``(``len``(str1)):``        ``obj.Union(``ord``(str1[i]) ``-` `97``, ``ord``(str2[i]) ``-` `97``)` `    ``# Loop to find the lexicographically smallest and``    ``# largest mapping for each character``    ``for` `i ``in` `range``(``len``(str3)):``        ``for` `j ``in` `range``(``ord``(``'a'``), ``ord``(``'z'``)``+``1``):``            ``if` `obj.find(``ord``(str3[i]) ``-` `97``) ``=``=` `obj.find(j ``-` `97``):``                ``st ``=` `ans[``0``][``0``]``                ``ans[``0``][``0``] ``=` `st ``+` `chr``(j)``                ``break` `        ``for` `j ``in` `range``(``ord``(``'z'``), ``ord``(``'a'``) ``-` `1``, ``-``1``):``            ``if` `obj.find(``ord``(str3[i]) ``-` `97``) ``=``=` `obj.find(j ``-` `97``):``                ``st ``=` `ans[``0``][``1``]``                ``ans[``0``][``1``] ``=` `st ``+` `chr``(j)``                ``break` `    ``# Return the pair of string``    ``return` `ans` `# Driver Code``if` `__name__ ``=``=` `'__main__'``:``    ``str1 ``=` `"geeksgeeks"``    ``str2 ``=` `"dedication"``    ``str3 ``=` `"truegeek"` `    ``# Function Call``    ``result ``=` `printTransitive(str1, str2, str3)``    ``print``(result[``0``][``0``] ``+` `" "` `+` `result[``0``][``1``])` `# This code is contributed by Tapesh (tapeshdua420)`

## C#

 `// Include namespace system``using` `System;``using` `System.Collections.Generic;``using` `System.Linq;``using` `System.Collections;` `public` `class` `GFG``{``  ` `    ``// Class to utilize disjoint set union.``    ``class` `DisjSet``    ``{``        ``public` `int``[] rank;``        ``public` `int``[] parent;``        ``public` `int` `n;``      ` `        ``// Constructor to create and``        ``// initialize sets of n items``        ``public` `DisjSet(``int` `n)``        ``{``            ``this``.rank = ``new` `int``[n];``            ``this``.parent = ``new` `int``[n];``            ``this``.n = n;``            ``this``.makeSet();``        ``}``      ` `        ``// Creates n single item sets``        ``public` `void` `makeSet()``        ``{``            ``for` `(``int` `i = 0; i < ``this``.n; i++)``            ``{``                ``this``.parent[i] = i;``            ``}``        ``}``      ` `        ``// Finds set of given item x``        ``public` `int` `find(``int` `x)``        ``{``          ` `            ``// Finds the representative of``            ``// the set that x is an element of``            ``if` `(``this``.parent[x] != x)``            ``{``              ` `                ``// If x is not the parent of``                ``// itself, then x is not the``                ``// representative of it's set,``                ``this``.parent[x] = ``this``.find(``this``.parent[x]);``            ``}``            ``return` `this``.parent[x];``        ``}``      ` `        ``// Do union of two sets represented``        ``// by x and y``        ``public` `void` `Union(``int` `x, ``int` `y)``        ``{``          ` `            ``// Find current sets of x and y``            ``var` `xset = ``this``.find(x);``            ``var` `yset = ``this``.find(y);``          ` `            ``// If they are already in same set``            ``if` `(xset == yset)``            ``{``                ``return``;``            ``}``          ` `            ``// Put smaller ranked item under``            ``// bigger ranked item if ranks are``            ``// different``            ``if` `(``this``.rank[xset] < ``this``.rank[yset])``            ``{``                ``this``.parent[xset] = yset;``            ``}``            ``else` `if` `(``this``.rank[xset] > ``this``.rank[yset])``            ``{``                ``this``.parent[yset] = xset;``            ``}``            ``else``            ``{``                ``this``.parent[yset] = xset;``                ``this``.rank[xset] = ``this``.rank[xset] + 1;``            ``}``        ``}``    ``}``  ` `    ``// Function to find the lexicographically``    ``// smallest and largest string``    ``public` `static` `List> printTransitive(String str1, String str2, String str3)``    ``{``        ``var` `obj = ``new` `DisjSet(26);``        ``var` `ans = ``new` `List>();``        ``if` `(str1.Length != str2.Length)``        ``{``            ``var` `temp = ``new` `List();``            ``temp.Add(``"All characters"``);``            ``temp.Add(``"not mapped"``);``            ``ans.Add(temp);``            ``return` `ans;``        ``}``        ``var` `temp1 = ``new` `List();``        ``temp1.Add(``""``);``        ``temp1.Add(``""``);``        ``ans.Add(temp1);``        ``for` `(``int` `i = 0; i < str1.Length; i++)``        ``{``            ``obj.Union((``int``)(str1[i]) - 97, (``int``)(str2[i]) - 97);``        ``}``        ``// Loop to find the lexicographically smallest and``        ``// largest mapping for each character``        ``for` `(``int` `i = 0; i < str3.Length; i++)``        ``{``            ``for` `(``char` `j = ``'a'``; j <= ``'z'``; j++)``            ``{``                ``if` `(obj.find((``int``)(str3[i]) - 97) == obj.find((``int``)(j) - 97))``                ``{``                    ``var` `st = ans[0][0];``                    ``ans[0][0] = st + j.ToString();``                    ``break``;``                ``}``            ``}``            ``for` `(``char` `j = ``'z'``; j >= ``'a'``; j--)``            ``{``                ``if` `(obj.find((``int``)(str3[i]) - 97) == obj.find((``int``)(j) - 97))``                ``{``                    ``var` `st = ans[0][1];``                    ``ans[0][1] = st + j.ToString();``                    ``break``;``                ``}``            ``}``        ``}``      ` `        ``// Return the pair of string``        ``return` `ans;``    ``}``  ` `    ``// Driver Code``    ``public` `static` `void` `Main(String[] args)``    ``{``        ``var` `str1 = ``"geeksgeeks"``;``        ``var` `str2 = ``"dedication"``;``        ``var` `str3 = ``"truegeek"``;``      ` `        ``// Function Call``        ``var` `result = GFG.printTransitive(str1, str2, str3);``        ``Console.WriteLine(result[0][0] + ``" "` `+ result[0][1]);``    ``}``}` `// This code is contributed by aadityapburujwale.`

## Javascript

 ``

Output

`aruaaaaa truttttt`

Time Complexity: O(M + N*26), where M and N are lengths of string str1 and str3.
Auxiliary Space: O(26)

My Personal Notes arrow_drop_up