Print all longest common sub-sequences in lexicographical order

22 Jun, 2022
You are given two strings. Now you have to print all longest common sub-sequences in lexicographical order?Examples:  
Input : str1 = "abcabcaa", str2 = "acbacba"
Output: ababa
        abaca
        abcba
        acaba
        acaca
        acbaa
        acbca
 
This problem is an extension of longest common subsequence. We first find length of LCS and store all LCS in 2D table using Memoization (or Dynamic Programming). Then we search all characters from ‘a’ to ‘z’ (to output sorted order) in both strings. If a character is found in both strings and current positions of character lead to LCS, we recursively search all occurrences with current LCS length plus 1. Below is the implementation of algorithm.  
C++
Java
Python3
C#
Javascript
// C++ program to find all LCS of two strings in// sorted order.#include<bits/stdc++.h>#define MAX 100using namespace std; // length of lcsint lcslen = 0; // dp matrix to store result of sub calls for lcsint dp[MAX][MAX]; // A memoization based function that returns LCS of// str1[i..len1-1] and str2[j..len2-1]int lcs(string str1, string str2, int len1, int len2,                                      int i, int j){    int &ret = dp[i][j];     // base condition    if (i==len1 || j==len2)        return ret = 0;     // if lcs has been computed    if (ret != -1)        return ret;     ret = 0;     // if characters are same return previous + 1 else    // max of two sequences after removing i'th and j'th    // char one by one    if (str1[i] == str2[j])        ret = 1 + lcs(str1, str2, len1, len2, i+1, j+1);    else        ret = max(lcs(str1, str2, len1, len2, i+1, j),                  lcs(str1, str2, len1, len2, i, j+1));    return ret;} // Function to print all routes common sub-sequences of// length lcslenvoid printAll(string str1, string str2, int len1, int len2,              char data[], int indx1, int indx2, int currlcs){    // if currlcs is equal to lcslen then print it    if (currlcs == lcslen)    {        data[currlcs] = '\0';        puts(data);        return;    }     // if we are done with all the characters of both string    if (indx1==len1 || indx2==len2)        return;     // here we have to print all sub-sequences lexicographically,    // that's why we start from 'a'to'z' if this character is    // present in both of them then append it in data[] and same    // remaining part    for (char ch='a'; ch<='z'; ch++)    {        // done is a flag to tell that we have printed all the        // subsequences corresponding to current character        bool done = false;         for (int i=indx1; i<len1; i++)        {            // if character ch is present in str1 then check if            // it is present in str2            if (ch==str1[i])            {              for (int j=indx2; j<len2; j++)              {                // if ch is present in both of them and                // remaining length is equal to remaining                // lcs length then add ch in sub-sequence                if (ch==str2[j] &&                  dp[i][j] == lcslen-currlcs)                {                  data[currlcs] = ch;                  printAll(str1, str2, len1, len2, data, i+1, j+1, currlcs+1);                  done = true;                  break;                }              }            }             // If we found LCS beginning with current character.            if (done)                break;        }    }} // This function prints all LCS of str1 and str2// in lexicographic order.void prinlAllLCSSorted(string str1, string str2){    // Find lengths of both strings    int len1 = str1.length(), len2 = str2.length();     // Find length of LCS    memset(dp, -1, sizeof(dp));    lcslen = lcs(str1, str2, len1, len2, 0, 0);     // Print all LCS using recursive backtracking    // data[] is used to store individual LCS.    char data[MAX];    printAll(str1, str2, len1, len2, data, 0, 0, 0);} // Driver program to run the caseint main(){    string str1 = "abcabcaa", str2 = "acbacba";    prinlAllLCSSorted(str1, str2);    return 0;}
// Java program to find all LCS of two strings in// sorted order.class GFG{  static int MAX = 100;   // length of lcs  static int lcslen = 0;   // dp matrix to store result of sub calls for lcs  static int[][] dp = new int[MAX][MAX];   // A memoization based function that returns LCS of  // str1[i..len1-1] and str2[j..len2-1]  static int lcs(String str1, String str2,                 int len1, int len2, int i, int j)  {    int ret = dp[i][j];     // base condition    if (i == len1 || j == len2)      return ret = 0;     // if lcs has been computed    if (ret != -1)      return ret;          ret = 0;     // if characters are same return previous + 1 else    // max of two sequences after removing i'th and j'th    // char one by one    if (str1.charAt(i) == str2.charAt(j))      ret = 1 + lcs(str1, str2, len1, len2, i + 1, j + 1);    else      ret = Math.max(lcs(str1, str2, len1, len2, i + 1, j),                     lcs(str1, str2, len1, len2, i, j + 1));    return ret;  }   // Function to print all routes common sub-sequences of  // length lcslen  static void printAll(String str1, String str2, int len1, int len2,                       char[] data, int indx1, int indx2, int currlcs)  {     // if currlcs is equal to lcslen then print it    if (currlcs == lcslen)    {      data[currlcs] = '\0';      System.out.println(new String(data));      return;    }     // if we are done with all the characters of both string    if (indx1 == len1 || indx2 == len2)      return;     // here we have to print all sub-sequences lexicographically,    // that's why we start from 'a'to'z' if this character is    // present in both of them then append it in data[] and same    // remaining part    for (char ch ='a'; ch <='z'; ch++)    {       // done is a flag to tell that we have printed all the      // subsequences corresponding to current character      boolean done = false;       for (int i = indx1; i < len1; i++)      {         // if character ch is present in str1 then check if        // it is present in str2        if (ch == str1.charAt(i))        {          for (int j = indx2; j < len2; j++)          {             // if ch is present in both of them and            // remaining length is equal to remaining            // lcs length then add ch in sub-sequence            if (ch == str2.charAt(j) &&                dp[i][j] == lcslen - currlcs)            {              data[currlcs] = ch;              printAll(str1, str2, len1, len2,                       data, i + 1, j + 1, currlcs + 1);              done = true;              break;            }          }        }         // If we found LCS beginning with current character.         if (done)          break;      }    }  }   // This function prints all LCS of str1 and str2  // in lexicographic order.  static void prinlAllLCSSorted(String str1, String str2)  {     // Find lengths of both strings    int len1 = str1.length(), len2 = str2.length();     // Find length of LCS    for(int i = 0; i < MAX; i++)    {      for(int j = 0; j < MAX; j++)      {        dp[i][j] = -1;      }    }    lcslen = lcs(str1, str2, len1, len2, 0, 0);     // Print all LCS using recursive backtracking    // data[] is used to store individual LCS.    char[] data = new char[MAX];    printAll(str1, str2, len1, len2, data, 0, 0, 0);  }   // Driver code  public static void main(String[] args)  {    String str1 = "abcabcaa", str2 = "acbacba";    prinlAllLCSSorted(str1, str2);  }} // This code is contributed by divyesh072019
# Python3 program to find all LCS of two strings in# sorted order.MAX=100lcslen = 0 # dp matrix to store result of sub calls for lcsdp=[[-1 for i in range(MAX)] for i in range(MAX)] # A memoization based function that returns LCS of# str1[i..len1-1] and str2[j..len2-1]def lcs(str1, str2, len1, len2, i, j):     # base condition    if (i == len1 or j == len2):        dp[i][j] = 0        return dp[i][j]     # if lcs has been computed    if (dp[i][j] != -1):        return dp[i][j]     ret = 0     # if characters are same return previous + 1 else    # max of two sequences after removing i'th and j'th    # char one by one    if (str1[i] == str2[j]):        ret = 1 + lcs(str1, str2, len1, len2, i + 1, j + 1)    else:        ret = max(lcs(str1, str2, len1, len2, i + 1, j),                  lcs(str1, str2, len1, len2, i, j + 1))    dp[i][j] = ret    return ret # Function to print all routes common sub-sequences of# length lcslendef printAll(str1, str2, len1, len2,data, indx1, indx2, currlcs):         # if currlcs is equal to lcslen then print    if (currlcs == lcslen):        print("".join(data[:currlcs]))        return     # if we are done with all the characters of both string    if (indx1 == len1 or indx2 == len2):        return     # here we have to print all sub-sequences lexicographically,    # that's why we start from 'a'to'z' if this character is    # present in both of them then append it in data[] and same    # remaining part    for ch in range(ord('a'),ord('z') + 1):         # done is a flag to tell that we have printed all the        # subsequences corresponding to current character        done = False         for i in range(indx1,len1):            # if character ch is present in str1 then check if            # it is present in str2            if (chr(ch)==str1[i]):              for j in range(indx2, len2):                 # if ch is present in both of them and                # remaining length is equal to remaining                # lcs length then add ch in sub-sequence                if (chr(ch) == str2[j] and dp[i][j] == lcslen-currlcs):                  data[currlcs] = chr(ch)                  printAll(str1, str2, len1, len2, data, i + 1, j + 1, currlcs + 1)                  done = True                  break             # If we found LCS beginning with current character.            if (done):                break # This function prints all LCS of str1 and str2# in lexicographic order.def prinlAllLCSSorted(str1, str2):    global lcslen    # Find lengths of both strings    len1,len2 = len(str1),len(str2)     lcslen = lcs(str1, str2, len1, len2, 0, 0)     # Print all LCS using recursive backtracking    # data[] is used to store individual LCS.    data = ['a' for i in range(MAX)]    printAll(str1, str2, len1, len2, data, 0, 0, 0) # Driver program to run the caseif __name__ == '__main__':    str1 = "abcabcaa"    str2 = "acbacba"    prinlAllLCSSorted(str1, str2) # This code is contributed by mohit kumar 29
// C# program to find all LCS of two strings in// sorted order.using System;class GFG{       static int MAX = 100;         // length of lcs    static int lcslen = 0;           // dp matrix to store result of sub calls for lcs    static int[,] dp = new int[MAX,MAX];           // A memoization based function that returns LCS of    // str1[i..len1-1] and str2[j..len2-1]    static int lcs(string str1, string str2,                   int len1, int len2, int i, int j)    {        int ret = dp[i, j];               // base condition        if (i == len1 || j == len2)            return ret = 0;               // if lcs has been computed        if (ret != -1)            return ret;               ret = 0;               // if characters are same return previous + 1 else        // max of two sequences after removing i'th and j'th        // char one by one        if (str1[i] == str2[j])            ret = 1 + lcs(str1, str2, len1, len2, i + 1, j + 1);        else            ret = Math.Max(lcs(str1, str2, len1, len2, i + 1, j),                      lcs(str1, str2, len1, len2, i, j + 1));        return ret;    }           // Function to print all routes common sub-sequences of    // length lcslen    static void printAll(string str1, string str2, int len1, int len2,                  char[] data, int indx1, int indx2, int currlcs)    {        // if currlcs is equal to lcslen then print it        if (currlcs == lcslen)        {            data[currlcs] = '\0';            Console.WriteLine(new string(data));            return;        }               // if we are done with all the characters of both string        if (indx1 == len1 || indx2 == len2)            return;               // here we have to print all sub-sequences lexicographically,        // that's why we start from 'a'to'z' if this character is        // present in both of them then append it in data[] and same        // remaining part        for (char ch='a'; ch<='z'; ch++)        {            // done is a flag to tell that we have printed all the            // subsequences corresponding to current character            bool done = false;                   for (int i = indx1; i < len1; i++)            {                // if character ch is present in str1 then check if                // it is present in str2                if (ch == str1[i])                {                  for (int j = indx2; j < len2; j++)                  {                    // if ch is present in both of them and                    // remaining length is equal to remaining                    // lcs length then add ch in sub-sequence                    if (ch == str2[j] &&                      lcs(str1, str2, len1, len2, i, j) == lcslen-currlcs)                    {                      data[currlcs] = ch;                      printAll(str1, str2, len1, len2, data, i+1, j+1, currlcs+1);                      done = true;                      break;                    }                  }                }                       // If we found LCS beginning with current character.                 if (done)                    break;            }        }    }           // This function prints all LCS of str1 and str2    // in lexicographic order.    static void prinlAllLCSSorted(string str1, string str2)    {        // Find lengths of both strings        int len1 = str1.Length, len2 = str2.Length;               // Find length of LCS        for(int i = 0; i < MAX; i++)        {            for(int j = 0; j < MAX; j++)            {                dp[i, j] = -1;            }        }        lcslen = lcs(str1, str2, len1, len2, 0, 0);               // Print all LCS using recursive backtracking        // data[] is used to store individual LCS.        char[] data = new char[MAX];        printAll(str1, str2, len1, len2, data, 0, 0, 0);    }   // Driver code  static void Main()  {    string str1 = "abcabcaa", str2 = "acbacba";    prinlAllLCSSorted(str1, str2);  }} // This code is contributed by divyeshrabadiya07
<script>// Javascript program to find all LCS of two strings in// sorted order.         let  MAX = 100;    // length of lcs    let lcslen = 0;         // dp matrix to store result of sub calls for lcs    let dp = new Array(MAX);         // A memoization based function that returns LCS of  // str1[i..len1-1] and str2[j..len2-1]    function lcs(str1,str2,len1,len2,i,j)    {        let ret = dp[i][j];      // base condition    if (i == len1 || j == len2)      return ret = 0;      // if lcs has been computed    if (ret != -1)      return ret;         ret = 0;      // if characters are same return previous + 1 else    // max of two sequences after removing i'th and j'th    // char one by one    if (str1[i] == str2[j])      ret = 1 + lcs(str1, str2, len1, len2, i + 1, j + 1);    else      ret = Math.max(lcs(str1, str2, len1, len2, i + 1, j),                     lcs(str1, str2, len1, len2, i, j + 1));    return ret;    }         // Function to print all routes common sub-sequences of  // length lcslen    function printAll(str1,str2,len1,len2,data,indx1,indx2,currlcs)    {        // if currlcs is equal to lcslen then print it    if (currlcs == lcslen)    {      data[currlcs] = null;      document.write(data.join("")+"<br>");      return;    }      // if we are done with all the characters of both string    if (indx1 == len1 || indx2 == len2)      return;      // here we have to print all sub-sequences lexicographically,    // that's why we start from 'a'to'z' if this character is    // present in both of them then append it in data[] and same    // remaining part    for (let ch ='a'.charCodeAt(0); ch <='z'.charCodeAt(0); ch++)    {                // done is a flag to tell that we have printed all the      // subsequences corresponding to current character      let done = false;        for (let i = indx1; i < len1; i++)      {          // if character ch is present in str1 then check if        // it is present in str2        if (ch == str1[i].charCodeAt(0))        {          for (let j = indx2; j < len2; j++)          {              // if ch is present in both of them and            // remaining length is equal to remaining            // lcs length then add ch in sub-sequence            if (ch == str2[j].charCodeAt(0) &&                lcs(str1, str2, len1, len2, i, j) == lcslen - currlcs)            {              data[currlcs] = String.fromCharCode(ch);              printAll(str1, str2, len1, len2,                       data, i + 1, j + 1, currlcs + 1);              done = true;              break;            }          }        }          // If we found LCS beginning with current character.        if (done)          break;      }    }    }         // This function prints all LCS of str1 and str2  // in lexicographic order.    function prinlAllLCSSorted(str1,str2)    {        // Find lengths of both strings    let len1 = str1.length, len2 = str2.length;      // Find length of LCS    for(let i = 0; i < MAX; i++)    {        dp[i]=new Array(MAX);      for(let j = 0; j < MAX; j++)      {        dp[i][j] = -1;      }    }    lcslen = lcs(str1, str2, len1, len2, 0, 0);      // Print all LCS using recursive backtracking    // data[] is used to store individual LCS.    let data = new Array(MAX);    printAll(str1, str2, len1, len2, data, 0, 0, 0);    }         // Driver code    let str1 = "abcabcaa", str2 = "acbacba";    prinlAllLCSSorted(str1, str2);          // This code is contributed by unknown2108</script>
ababa
abaca
abcba
acaba
acaca
acbaa
acbca
Time Complexity: O(m*n*p), where ‘m’ is the length of characters array, ‘n’ is the length of array1 and ‘p’ is the length of array2. 
This article is contributed by Shashak Mishra ( Gullu ). If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above. 
mohit kumar 29
divyeshrabadiya07
divyesh072019
unknown2108
chirags_30
sagartomar9927
varshagumber28
adnanirshad158
kanheremahesh1729
LCS
lexicographic-ordering
subsequence
Backtracking
Dynamic Programming
Recursion
Dynamic Programming
Recursion
Backtracking
LCS
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.