Open In App

Shortest Supersequence by Sequence Reconstruction

Given an array arr[] and a 2D array sequences[], determine if arr is the shortest possible and the only supersequence for the given sequences. A supersequence is a sequence that has all sequences[i] as subsequences. The task is to return true if arr is the only shortest supersequence for sequences, or false otherwise.

Example:

Input: arr = {1,2,3}, sequences = {{1,2},{1,3}}
Output: false
Explanation: There are two possible supersequences: {1,2,3} and {1,3,2}.

  • The sequence {1,2} is a subsequence of both: {1,2,3} and {1,3,2}.
  • The sequence {1,3} is a subsequence of both: {1,2,3} and {1,3,2}.
  • As arr is not the only shortest supersequence, the output is false.

Input: arr = {1,2,3}, sequences = {{1,2}}
Output: false
Explanation: The shortest possible supersequence is {1,2}.

  • The sequence {1,2} is a subsequence of it: {1,2}.
  • Since arr is not the shortest supersequence, we return false.

Approach:

The basic is to get topological sort of sequences nodes, if it is unique and equal to arr, then true, else False. Following is how to implement in details:

In each step of topological sorting, if we have more than one node whose incoming nodes count is zero then the togological ordering will not be unique, hence our supersequence won't be unique. So, return False. At last we check if the topological sort contain all nodes in the in seqs and equal to our generated supersequence.

Steps-by-step approach:

Below is the implementation of the above approach:

#include <bits/stdc++.h>
using namespace std;

// Function to check if arr is the only shortest
// supersequence for sequences
bool sequenceReconstruction(vector<int>& arr,
                            vector<vector<int> >& sequences)
{
    int n = arr.size();

    // Create adjacency list to represent dependencies
    // between elements
    vector<vector<int> > adj(n + 1);
    // Store indegree of each element (number of elements
    // that must appear before it)
    vector<int> indegree(n + 1);

    // Build the dependency graph
    for (auto& seq : sequences) {
        for (int j = 0; j < seq.size() - 1; j++) {
            adj[seq[j]].push_back(seq[j + 1]);
            indegree[seq[j + 1]]++;
        }
    }

    // Perform topological sort using a queue
    queue<int> q;
    vector<int> result;

    // Add elements with indegree 0 to the queue (starting
    // points)
    for (int i = 1; i <= n; i++) {
        if (indegree[i] == 0) {
            q.push(i);
        }
    }

    // If there are multiple elements with indegree 0, it's
    // not the only supersequence
    if (q.size() > 1) {
        return false;
    }

    // Process elements in topological order
    while (q.size()) {
        auto curr = q.front();
        result.push_back(curr);
        q.pop();

        // Update indegree of neighbors and add them to the
        // queue if they become ready
        for (auto c : adj[curr]) {
            indegree[c]--;
            if (indegree[c] == 0) {
                q.push(c);
            }
        }

        // If there are multiple elements ready at the same
        // time, it's not the only supersequence
        if (q.size() > 1) {
            return false;
        }
    }

    // Check if the resulting sequence is the same as the
    // given array and has the same length
    return (result == arr);
}

// Driver code
int main()
{
    vector<int> arr = { 1, 2, 3 };
    vector<vector<int> > sequences = { { 1, 2 }, { 1, 3 } };
    bool result = sequenceReconstruction(arr, sequences);

    if (result) {
        cout << "True" << endl;
    }
    else {
        cout << "False" << endl;
    }
    return 0;
}
import java.util.*;

public class Main {
    // Function to check if arr is the only shortest
    // supersequence for sequences
    static boolean
    sequenceReconstruction(List<Integer> arr,
                           List<List<Integer> > sequences)
    {
        int n = arr.size();

        // Create adjacency list to represent dependencies
        // between elements
        List<List<Integer> > adj = new ArrayList<>();
        for (int i = 0; i <= n; i++) {
            adj.add(new ArrayList<>());
        }

        // Store indegree of each element (number of
        // elements that must appear before it)
        int[] indegree = new int[n + 1];

        // Build the dependency graph
        for (List<Integer> seq : sequences) {
            for (int j = 0; j < seq.size() - 1; j++) {
                int from = seq.get(j);
                int to = seq.get(j + 1);
                adj.get(from).add(to);
                indegree[to]++;
            }
        }

        // Perform topological sort using a queue
        Queue<Integer> q = new LinkedList<>();
        List<Integer> result = new ArrayList<>();

        // Add elements with indegree 0 to the queue
        // (starting points)
        for (int i = 1; i <= n; i++) {
            if (indegree[i] == 0) {
                q.add(i);
            }
        }

        // If there are multiple elements with indegree 0,
        // it's not the only supersequence
        if (q.size() > 1) {
            return false;
        }

        // Process elements in topological order
        while (!q.isEmpty()) {
            int curr = q.poll();
            result.add(curr);

            // Update indegree of neighbors and add them to
            // the queue if they become ready
            for (int c : adj.get(curr)) {
                indegree[c]--;
                if (indegree[c] == 0) {
                    q.add(c);
                }
            }

            // If there are multiple elements ready at the
            // same time, it's not the only supersequence
            if (q.size() > 1) {
                return false;
            }
        }

        // Check if the resulting sequence is the same as
        // the given array and has the same length
        return result.equals(arr);
    }

    // Driver code
    public static void main(String[] args)
    {
        List<Integer> arr = Arrays.asList(1, 2, 3);
        List<List<Integer> > sequences = Arrays.asList(
            Arrays.asList(1, 2), Arrays.asList(1, 3));
        boolean result
            = sequenceReconstruction(arr, sequences);

        if (result) {
            System.out.println("True");
        }
        else {
            System.out.println("False");
        }
    }
}

// This code is contributed by shivamgupta310570
from collections import deque

# Function to check if arr is the only shortest
# supersequence for sequences
def sequenceReconstruction(arr, sequences):
    n = len(arr)

    # Create adjacency list to represent dependencies
    # between elements
    adj = [[] for _ in range(n + 1)]
    # Store indegree of each element (number of elements
    # that must appear before it)
    indegree = [0] * (n + 1)

    # Build the dependency graph
    for seq in sequences:
        for j in range(len(seq) - 1):
            adj[seq[j]].append(seq[j + 1])
            indegree[seq[j + 1]] += 1

    # Perform topological sort using a queue
    q = deque()
    result = []

    # Add elements with indegree 0 to the queue (starting
    # points)
    for i in range(1, n + 1):
        if indegree[i] == 0:
            q.append(i)

    # If there are multiple elements with indegree 0, it's
    # not the only supersequence
    if len(q) > 1:
        return False

    # Process elements in topological order
    while q:
        curr = q.popleft()
        result.append(curr)

        # Update indegree of neighbors and add them to the
        # queue if they become ready
        for c in adj[curr]:
            indegree[c] -= 1
            if indegree[c] == 0:
                q.append(c)

        # If there are multiple elements ready at the same
        # time, it's not the only supersequence
        if len(q) > 1:
            return False

    # Check if the resulting sequence is the same as the
    # given array and has the same length
    return result == arr

# Driver code
if __name__ == "__main__":
    arr = [1, 2, 3]
    sequences = [[1, 2], [1, 3]]
    result = sequenceReconstruction(arr, sequences)

    if result:
        print("True")
    else:
        print("False")

        # This code is contributed by Ayush Mishra
function sequenceReconstruction(arr, sequences) {
    const n = arr.length;

    // Create adjacency list to represent dependencies between elements
    const adj = Array.from({ length: n + 1 }, () => []);
    // Store indegree of each element (number of elements that must appear before it)
    const indegree = Array(n + 1).fill(0);

    // Build the dependency graph
    sequences.forEach(seq => {
        for (let j = 0; j < seq.length - 1; j++) {
            adj[seq[j]].push(seq[j + 1]);
            indegree[seq[j + 1]]++;
        }
    });

    // Perform topological sort using a queue
    const q = [];
    const result = [];

    // Add elements with indegree 0 to the queue (starting points)
    for (let i = 1; i <= n; i++) {
        if (indegree[i] === 0) {
            q.push(i);
        }
    }

    // If there are multiple elements with indegree 0, it's not the only supersequence
    if (q.length > 1) {
        return false;
    }

    // Process elements in topological order
    while (q.length > 0) {
        const curr = q.shift();
        result.push(curr);

        // Update indegree of neighbors and add them to the queue if they become ready
        for (const c of adj[curr]) {
            indegree[c]--;
            if (indegree[c] === 0) {
                q.push(c);
            }
        }

        // If there are multiple elements ready at the same time, it's not the 
        //only supersequence
        
        if (q.length > 1) {
            return false;
        }
    }

    // Check if the resulting sequence is the same as the given array 
    //and has the same length
    
    return JSON.stringify(result) === JSON.stringify(arr);
}

// Driver code
const arr = [1, 2, 3];
const sequences = [[1, 2], [1, 3]];
const result = sequenceReconstruction(arr, sequences);

if (result) {
    console.log("True");
} else {
    console.log("False");
}

Output
False

Time Complexity: O(S + N), where S is the total number of elements in all sequences and N is the number of elements in the array arr.
Auxiliary Space: O(S + N)

Article Tags :