Check if given Arrays have a Unique Shortest Common Super-sequence
Given a 2D array arr[][] of size N*M which denotes N arrays, each of size M. The task is to check if all these arrays have a unique common supersequence.
Examples:
Input: N = 2, M = 2, arr[][] = { { 1, 2 }, {1, 3 } }
Output: False
Explanation: There are two possible supersequence: {1, 3, 2 } and {1, 2, 3}.Input: N = 3, M = 2, arr[][] = { { 1, 2 }, {1, 3}, {2, 3 } }
Output: True
Explanation: { 1, 2, 3 } is the only shortest common supersequence of {1, 2}, {1, 3} and {2, 3}.
Approach: The idea is to use topological sorting, Follow the steps mentioned below to solve the problem:
- Represent the sequences in the ‘arr[][]’ by a directed graph and find its topological sort order.
- If there is only one topological sort order, then it can be said that there is only one shortest common supersequence.
- Otherwise, return false.
Below is the implementation of the above approach.
C++
// C++ code for the above approach #include <bits/stdc++.h> using namespace std; // Function to check unique // shortest common supersequence bool shortestSuperSeq(vector<vector< int > >& arr, int N, int M) { // Initializing map to store // edges and indegree of vertices unordered_map< int , vector< int > > adj; unordered_map< int , int > indegree; // Initializing all keys of map // with values of sequences in arr for ( int i = 0; i < N; i++) { for ( int j = 0; j < M; j++) { int node = arr[i][j]; adj[node] = {}; indegree[node] = 0; } } // For every sequence in arr // calculate indegree and edges. for ( auto seq : arr) { for ( int i = 1; i < M; i++) { adj[seq[i - 1]].push_back(seq[i]); indegree[seq[i]]++; } } // Vector to store // topologically sorted order. vector< int > res; queue< int > q; // Push vertices with 0 indegree in queue for ( auto itr : indegree) { if (itr.second == 0) { q.push(itr.first); } } while (!q.empty()) { int size = q.size(); // If size of q > 1, this means // more than one choices, // so no unique common supersequence // can be formed. if (size != 1) return false ; int node = q.front(); // Add node to topological sort order res.push_back(node); q.pop(); // Decrement indegree of all // the vertices connected to node for ( int i = 0; i < adj[node].size(); i++) { int connected_node = adj[node][i]; // Push vertices with 0 indegree // to queue if ((--indegree[connected_node]) == 0) { q.push(connected_node); } } } // If indegree of any vertices is not 0, // return false. for ( auto itr : indegree) { if (itr.second != 0) return false ; } return true ; } // Driver Code int main() { vector<vector< int > > arr = { { 1, 2 }, { 1, 3 } }; int N = arr.size(), M = arr[0].size(); if (shortestSuperSeq(arr, N, M)) cout << "True\n" ; else cout << "False\n" ; return 0; } |
Java
import java.io.*; import java.util.*; class GFG { // Function to check unique // shortest common supersequence public static boolean shortestSuperSeq(ArrayList<ArrayList<Integer> > arr, int N, int M) { // Initializing map to store // edges and indegree of vertices HashMap<Integer, ArrayList<Integer> > adj = new HashMap<>(); HashMap<Integer, Integer> indegree = new HashMap<>(); // Initializing all keys of map // with values of sequences in arr for ( int i = 0 ; i < N; i++) { for ( int j = 0 ; j < M; j++) { int node = arr.get(i).get(j); ArrayList<Integer> temp = new ArrayList<Integer>(); adj.put(node, temp); indegree.put(node, 0 ); } } // For every sequence in arr // calculate indegree and edges. for (ArrayList<Integer> seq : arr) { for ( int i = 1 ; i < M; i++) { adj.get(seq.get(i - 1 )).add(seq.get(i)); int temp = indegree.get(seq.get(i)); indegree.put(seq.get(i), temp + 1 ); } } // ArrayList to store // topologically sorted order. ArrayList<Integer> res = new ArrayList<Integer>(); ArrayDeque<Integer> q = new ArrayDeque<>(); // Push vertices with 0 indegree in queue for ( int itr : indegree.keySet()) { if (indegree.get(itr) == 0 ) { q.addLast(itr); } } while (q.size() > 0 ) { int size = q.size(); // If size of q > 1, this means // more than one choices, // so no unique common supersequence // can be formed. if (size != 1 ) return false ; int node = q.getFirst(); // Add node to topological sort order res.add(node); q.removeLast(); // Decrement indegree of all // the vertices connected to node for ( int i = 0 ; i < adj.get(node).size(); i++) { int connected_node = adj.get(node).get(i); // Push vertices with 0 indegree // to queue int temp = indegree.get(connected_node) - 1 ; indegree.put(connected_node, temp); if ((temp == 0 )) { q.addLast(connected_node); } } } // If indegree of any vertices is not 0, // return false. for ( int itr : indegree.keySet()) { if (indegree.get(itr) != 0 ) return false ; } return true ; } // Driver Code public static void main(String[] args) { ArrayList<ArrayList<Integer> > arr = new ArrayList<ArrayList<Integer> >(); arr.add( new ArrayList<Integer>(Arrays.asList( 1 , 2 ))); arr.add( new ArrayList<Integer>(Arrays.asList( 1 , 3 ))); int N = arr.size(), M = arr.get( 0 ).size(); if (shortestSuperSeq(arr, N, M)) System.out.println( "True" ); else System.out.println( "False" ); } } // This code is contributed by Palak Gupta |
Python3
# Python code for the above approach # Function to check unique # shortest common supersequence def shortestSuperSeq(arr, N, M): # Initializing map to store # edges and indegree of vertices adj = {} indegree = {} # Initializing all keys of map # with values of sequences in arr for i in range (N): for j in range (M): node = arr[i][j]; adj[node] = [] indegree[node] = 0 # For every sequence in arr # calculate indegree and edges. for seq in arr: for i in range ( 1 , M): adj[seq[i - 1 ]].append(seq[i]); indegree[seq[i]] + = 1 # Vector to store # topologically sorted order. res = []; q = []; # Push vertices with 0 indegree in queue for k in indegree.keys(): if (indegree[k] = = 0 ): q.append(k); while ( len (q) ! = 0 ): size = len (q) # If size of q > 1, this means # more than one choices, # so no unique common supersequence # can be formed. if (size ! = 1 ): return False ; node = q.pop( 0 ); # Add node to topological sort order res.append(node); # Decrement indegree of all # the vertices connected to node for i in range ( len (adj[node])): connected_node = adj[node][i]; # Push vertices with 0 indegree # to queue indegree[connected_node] - = 1 if (indegree[connected_node] = = 0 ): q.append(connected_node); # If indegree of any vertices is not 0, # return false. for itr in indegree.keys(): if (itr ! = 0 ): return False ; return True ; # Driver Code arr = [[ 1 , 2 ], [ 1 , 3 ]]; N = len (arr) M = len (arr[ 0 ]) if (shortestSuperSeq(arr, N, M)): print ( "True" ); else : print ( "False" ) # This code is contributed by Saurabh Jaiswal |
C#
// C# program to implement above approach using System; using System.Collections; using System.Collections.Generic; class GFG { // Function to check unique // shortest common supersequence static bool shortestSuperSeq(List<List< int >> arr, int N, int M) { // Initializing map to store // edges and indegree of vertices Dictionary< int , List< int >> adj = new Dictionary< int , List< int >>(); Dictionary< int , int > indegree = new Dictionary< int , int >(); // Initializing all keys of map // with values of sequences in arr for ( int i = 0 ; i < N ; i++) { for ( int j = 0 ; j < M ; j++) { int node = arr[i][j]; if (!adj.ContainsKey(node)){ adj.Add(node, new List< int >()); indegree.Add(node, 0); } } } // For every sequence in arr // calculate indegree and edges. foreach (List< int > seq in arr) { for ( int i = 1 ; i < M ; i++) { if (!adj.ContainsKey(seq[i-1])){ adj.Add(seq[i-1], new List< int >()); } adj[seq[i-1]].Add(seq[i]); if (!indegree.ContainsKey(seq[i])){ indegree.Add(seq[i], 0); } int temp = indegree[seq[i]]; indegree[seq[i]] = temp + 1; } } // ArrayList to store // topologically sorted order. List< int > res = new List< int >(); List< int > q = new List< int >(); // Pointers to first and last element of deque int l = 0, r = -1; // Push vertices with 0 indegree in queue foreach (KeyValuePair< int , int > itr in indegree) { if (indegree[itr.Key] == 0) { q.Add(itr.Key); r++; } } while (l <= r) { int size = r - l + 1; // If size of q > 1, this means // more than one choices, // so no unique common supersequence // can be formed. if (size != 1) return false ; int node = q[l]; // Add node to topological sort order res.Add(node); r--; // Decrement indegree of all // the vertices connected to node for ( int i = 0 ; i < adj[node].Count ; i++) { int connected_node = adj[node][i]; // Push vertices with 0 indegree // to queue int temp = indegree[connected_node] - 1; indegree[connected_node] = temp; if (temp == 0) { if (q.Count - 1 == r){ q.Add(connected_node); } else { q[r + 1] = connected_node; } r++; } } } // If indegree of any vertices is not 0, // return false. foreach (KeyValuePair< int , int > itr in indegree) { if (itr.Value != 0) return false ; } return true ; } public static void Main( string [] args){ List<List< int >> arr = new List<List< int >>(); arr.Add( new List< int >{1, 2}); arr.Add( new List< int >{1, 3}); int N = arr.Count; int M = arr[0].Count; if (shortestSuperSeq(arr, N, M)) Console.WriteLine( "True" ); else Console.WriteLine( "False" ); } } // This code is contributed by entertain2022. |
Javascript
<script> // JavaScript code for the above approach // Function to check unique // shortest common supersequence function shortestSuperSeq(arr, N, M) { // Initializing map to store // edges and indegree of vertices let adj = new Map(); let indegree = new Map(); // Initializing all keys of map // with values of sequences in arr for (let i = 0; i < N; i++) { for (let j = 0; j < M; j++) { let node = arr[i][j]; adj.set(node, []) indegree.set(node, 0); } } // For every sequence in arr // calculate indegree and edges. for (let seq of arr) { for (let i = 1; i < M; i++) { adj.get(seq[i - 1]).push(seq[i]); indegree.set(seq[i], indegree.get(seq[i]) + 1); } } // Vector to store // topologically sorted order. let res = []; let q = []; // Push vertices with 0 indegree in queue for (let [key, val] of indegree) { if (val == 0) { q.push(key); } } while (q.length != 0) { let size = q.length; // If size of q > 1, this means // more than one choices, // so no unique common supersequence // can be formed. if (size != 1) return false ; let node = q.shift(); // Add node to topological sort order res.push(node); // Decrement indegree of all // the vertices connected to node for (let i = 0; i < adj.get(node).length; i++) { let connected_node = adj.get(node)[i]; // Push vertices with 0 indegree // to queue indegree.set(connected_node, indegree.get(connected_node) - 1); if ((indegree.get(connected_node)) == 0) { q.push(connected_node); } } } // If indegree of any vertices is not 0, // return false. for (let itr of indegree.keys()) { if (itr != 0) return false ; } return true ; } // Driver Code let arr = [[1, 2], [1, 3]]; let N = arr.length, M = arr[0].length; if (shortestSuperSeq(arr, N, M)) document.write( "True" ); else document.write( "False" ) // This code is contributed by Potta Lokesh </script> |
Output
False
Time Complexity: O(N * M)
Auxiliary Space: O(N * M)
Please Login to comment...