Given a list of conversion tuples Arr[], such that string Arr[i][0] gets converted to string Arr[i][1]. A character is considered good if it has one-to-one mapping to some other character throughout all the conversions, for example during conversion of "abb" to "abc", b->c is considered good. Your task is to find the longest chain of good characters in the form x->y->z... where x,y, and z are good characters.
Examples:
Input: {{'ab', 'ac'}, {'yz', 'xz'},{'ee', 'ee'},{'aaac', 'abag'},{'g', 'h'}}
Output: {a, b, c, g, h}
Explanation:
tuple 1: b -> c.
tuple 2: y -> x.
tuple 3: no mutations occurred
tuple 4: a -> b, and c -> g
tuple 5: g -> h
the longest mutation sequence is ['a->b->c->g->h'].Input: { {"term", "team"},{"drift", "draft"}}
Output: { i, a }
Approach Using BFS:
The approach involves constructing a directed graph based on observed good conversions in the tuples, performing a modified BFS (Breadth-First Search) to traverse the graph, and updating the longest good chain, resulting in an efficient solution to identify the sequence of good character conversions.
Steps to solve the problem:
- Create a graph and Initialize adj (adjacency list) and ind (in-degree array).
- For each tuple in arr
- Compare corresponding letters of the first and second words.
- If different, update adj and ind based on the character changes.
- Initialize a queue qu with nodes having in-degree 0.
- Initialize variables ans (answer) and maxi (maximum chain length).
- While qu is not empty:
- Pop a node from qu.
- Traverse the chain of good characters:
- Add each letter to the ans.
- Update maxi if the current chain is longer.
- Push connected nodes with in-degree 0 to qu.
- Print the longest good character chain stored in ans.
Below is the implementation of the approach:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
void longestGoodSequence(vector<pair<string, string> >& arr,
vector<int> adj[],
vector<int>& ind)
{
// Initialize a queue with nodes having in-degree 0
queue<int> q;
for (int i = 0; i < 26; i++) {
if (ind[i] == 0) {
q.push(i);
}
}
// Variables to store the answer
vector<char> ans;
ll maxi = 1;
// Perform topological sort
while (q.empty() == false) {
vector<char> ans1;
int for1 = q.front();
q.pop();
ans1.push_back(for1 + 'a');
// Traverse the chain of mutations
while (adj[for1].size() > 0) {
ans1.push_back(adj[for1][0] + 'a');
for1 = adj[for1][0];
}
// Update the answer if the current chain is longer
if (ans1.size() > maxi) {
maxi = ans1.size();
ans = ans1;
}
}
// Output the result
for (int i = 0; i < ans.size(); i++) {
cout << ans[i] << " ";
}
}
int main()
{
// User-defined input for the tuples of words
vector<pair<string, string> > arr
= { { "ab", "ac" },
{ "yz", "xz" },
{ "ee", "ee" },
{ "aaac", "abag" },
{ "g", "h" } };
// Create adjacency list and in-degree array
vector<int> adj[26];
vector<int> ind(26, 0);
// Build the adjacency list and in-degree array
for (int i = 0; i < arr.size(); i++) {
ll len = arr[i].first.size();
for (int j = 0; j < len; j++) {
if (arr[i].first[j] != arr[i].second[j]) {
ll val1 = arr[i].first[j] - 'a';
ll val2 = arr[i].second[j] - 'a';
ind[val2]++;
adj[val1].push_back(val2);
}
}
}
longestGoodSequence(arr, adj, ind);
return 0;
}
import java.util.*;
public class GFG {
public static void longestGoodSequence(List<Pair<String, String>> arr, List<Integer>[] adj, List<Integer> ind) {
// Initialize a queue with nodes having in-degree 0
Queue<Integer> q = new LinkedList<>();
for (int i = 0; i < 26; i++) {
if (ind.get(i) == 0) {
q.add(i);
}
}
// Variables to store the answer
List<Character> ans = new ArrayList<>();
long maxi = 1;
// Perform topological sort
while (!q.isEmpty()) {
List<Character> ans1 = new ArrayList<>();
int for1 = q.poll();
ans1.add((char) (for1 + 'a'));
// Traverse the chain of mutations
while (!adj[for1].isEmpty()) {
ans1.add((char) (adj[for1].get(0) + 'a'));
for1 = adj[for1].get(0);
}
// Update the answer if the current chain is longer
if (ans1.size() > maxi) {
maxi = ans1.size();
ans = new ArrayList<>(ans1);
}
}
// Output the result
for (char c : ans) {
System.out.print(c + " ");
}
}
public static void main(String[] args) {
// User-defined input for the tuples of words
List<Pair<String, String>> arr = Arrays.asList(
new Pair<>("ab", "ac"),
new Pair<>("yz", "xz"),
new Pair<>("ee", "ee"),
new Pair<>("aaac", "abag"),
new Pair<>("g", "h")
);
// Create adjacency list and in-degree array
List<Integer>[] adj = new ArrayList[26];
for (int i = 0; i < 26; i++) {
adj[i] = new ArrayList<>();
}
List<Integer> ind = new ArrayList<>(Collections.nCopies(26, 0));
// Build the adjacency list and in-degree array
for (Pair<String, String> pair : arr) {
int len = pair.getFirst().length();
for (int j = 0; j < len; j++) {
if (pair.getFirst().charAt(j) != pair.getSecond().charAt(j)) {
int val1 = pair.getFirst().charAt(j) - 'a';
int val2 = pair.getSecond().charAt(j) - 'a';
ind.set(val2, ind.get(val2) + 1);
adj[val1].add(val2);
}
}
}
longestGoodSequence(arr, adj, ind);
}
static class Pair<K, V> {
private K first;
private V second;
public Pair(K first, V second) {
this.first = first;
this.second = second;
}
public K getFirst() {
return first;
}
public V getSecond() {
return second;
}
}
}
from collections import deque
def longest_good_sequence(arr, adj, ind):
# Initialize a queue with nodes having in-degree 0
q = deque([i for i in range(26) if ind[i] == 0])
# Variables to store the answer
ans = []
maxi = 1
# Perform topological sort
while q:
ans1 = []
for1 = q.popleft()
ans1.append(chr(for1 + ord('a')))
# Traverse the chain of mutations
while adj[for1]:
ans1.append(chr(adj[for1][0] + ord('a')))
for1 = adj[for1].pop(0)
# Update the answer if the current chain is longer
if len(ans1) > maxi:
maxi = len(ans1)
ans = ans1
# Output the result
print(" ".join(ans))
if __name__ == "__main__":
# User-defined input for the tuples of words
arr = [
("ab", "ac"),
("yz", "xz"),
("ee", "ee"),
("aaac", "abag"),
("g", "h")
]
# Create adjacency list and in-degree array
adj = [[] for _ in range(26)]
ind = [0] * 26
# Build the adjacency list and in-degree array
for tup in arr:
for j in range(len(tup[0])):
if tup[0][j] != tup[1][j]:
val1 = ord(tup[0][j]) - ord('a')
val2 = ord(tup[1][j]) - ord('a')
ind[val2] += 1
adj[val1].append(val2)
longest_good_sequence(arr, adj, ind)
using System;
using System.Collections.Generic;
public class GFG
{
public static void LongestGoodSequence(List<Pair<string, string>> arr, List<int>[] adj, List<int> ind)
{
// Initialize a queue with nodes having in-degree 0
Queue<int> q = new Queue<int>();
for (int i = 0; i < 26; i++)
{
if (ind[i] == 0)
{
q.Enqueue(i);
}
}
// Variables to store the answer
List<char> ans = new List<char>();
long maxi = 1;
// Perform topological sort
while (q.Count > 0)
{
List<char> ans1 = new List<char>();
int for1 = q.Dequeue();
ans1.Add((char)(for1 + 'a'));
// Traverse the chain of mutations
while (adj[for1].Count > 0)
{
ans1.Add((char)(adj[for1][0] + 'a'));
for1 = adj[for1][0];
}
// Update the answer if the current chain is longer
if (ans1.Count > maxi)
{
maxi = ans1.Count;
ans = new List<char>(ans1);
}
}
// Output the result
foreach (char c in ans)
{
Console.Write(c + " ");
}
}
public static void Main()
{
// User-defined input for the tuples of words
List<Pair<string, string>> arr = new List<Pair<string, string>>
{
new Pair<string, string>("ab", "ac"),
new Pair<string, string>("yz", "xz"),
new Pair<string, string>("ee", "ee"),
new Pair<string, string>("aaac", "abag"),
new Pair<string, string>("g", "h")
};
// Create adjacency list and in-degree array
List<int>[] adj = new List<int>[26];
for (int i = 0; i < 26; i++)
{
adj[i] = new List<int>();
}
List<int> ind = new List<int>(new int[26]);
// Build the adjacency list and in-degree array
foreach (var pair in arr)
{
int len = pair.First.Length;
for (int j = 0; j < len; j++)
{
if (pair.First[j] != pair.Second[j])
{
int val1 = pair.First[j] - 'a';
int val2 = pair.Second[j] - 'a';
ind[val2]++;
adj[val1].Add(val2);
}
}
}
LongestGoodSequence(arr, adj, ind);
}
public class Pair<K, V>
{
private K first;
private V second;
public Pair(K first, V second)
{
this.first = first;
this.second = second;
}
public K First { get { return first; } }
public V Second { get { return second; } }
}
}
<script>
// Function to find the longest good sequence
function longestGoodSequence(arr, adj, ind) {
let q = []; // Initialize an empty queue for nodes with in-degree 0
// Loop to add nodes with in-degree 0 to the queue
for (let i = 0; i < 26; i++) {
if (ind[i] === 0) {
q.push(i);
}
}
let ans = []; // Array to store the answer
let maxi = 1; // Variable to keep track of the maximum length found
// Loop until the queue is empty
while (q.length > 0) {
let ans1 = []; // Temporary array to store the current sequence
let for1 = q.shift(); // Remove and get the first element of the queue
ans1.push(String.fromCharCode(for1 + 'a'.charCodeAt(0))); // Convert the number to its corresponding character and add to the sequence
// Loop to traverse the chain of mutations
while (adj[for1].length > 0) {
ans1.push(String.fromCharCode(adj[for1][0] + 'a'.charCodeAt(0)));
for1 = adj[for1].shift(); // Move to the next mutation in the chain
}
// If the current sequence is longer than the maximum found so far, update the answer
if (ans1.length > maxi) {
maxi = ans1.length;
ans = ans1.slice(); // Copy the current sequence to the answer
}
}
// Output the answer
console.log(ans.join(" "));
}
function main() {
// User-defined input for the tuples of words
let arr = [
["ab", "ac"],
["yz", "xz"],
["ee", "ee"],
["aaac", "abag"],
["g", "h"]
];
// Create adjacency list and in-degree array
let adj = Array.from({length: 26}, () => []);
let ind = new Array(26).fill(0);
// Build the adjacency list and in-degree array based on the input
arr.forEach(pair => {
let len = pair[0].length;
for (let j = 0; j < len; j++) {
if (pair[0].charAt(j) !== pair[1].charAt(j)) {
let val1 = pair[0].charCodeAt(j) - 'a'.charCodeAt(0);
let val2 = pair[1].charCodeAt(j) - 'a'.charCodeAt(0);
ind[val2]++; // Increment in-degree for the destination node
adj[val1].push(val2); // Add an edge from the source node to the destination node
}
}
});
longestGoodSequence(arr, adj, ind); // Call the function to find and print the longest good sequence
}
main(); // Entry point of the program
</script>
Output
a b c g h
Time Complexity: O(N * M), where N is the number of tuples and M is the maximum length of words in a tuple
Auxiliary Space: O(N + M).