logo

Imprima todas las subsecuencias comunes más largas en orden lexicográfico

Pruébalo en GfG Practice ' title= #practiceLinkDiv { mostrar: ninguno !importante; }

Se le dan dos cadenas, la tarea es imprimir todas las subsecuencias comunes más largas en orden lexicográfico.

Ejemplos: 

Input : str1 = 'abcabcaa' str2 = 'acbacba' Output: ababa abaca abcba acaba acaca acbaa acbca
Recommended Practice Imprime todas las secuencias LCS ¡Pruébalo!

Este problema es una extensión de subsecuencia común más larga . Primero encontramos la longitud de LCS y almacenamos todos los LCS en una tabla 2D usando Memoización (o Programación dinámica). Luego buscamos todos los caracteres de 'a' a 'z' (para generar el orden ordenado) en ambas cadenas. Si se encuentra un carácter en ambas cadenas y las posiciones actuales del carácter conducen a LCS, buscamos recursivamente todas las apariciones con la longitud actual de LCS más 1. 



A continuación se muestra la implementación del algoritmo. 

C++
// C++ program to find all LCS of two strings in // sorted order. #include   #define MAX 100 using namespace std; // length of lcs int lcslen = 0; // dp matrix to store result of sub calls for lcs int 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 lcslen 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] = '';  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 case int main() {  string str1 = 'abcabcaa' str2 = 'acbacba';  prinlAllLCSSorted(str1 str2);  return 0; } 
Java
// Java program to find all LCS of two strings in  // sorted order.  import java.io.*; 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 dp[i][j]=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] = '';   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
# Python3 program to find all LCS of two strings in # sorted order. MAX=100 lcslen = 0 # dp matrix to store result of sub calls for lcs dp=[[-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 lcslen def printAll(str1 str2 len1 len2data 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(indx1len1): # 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 len1len2 = 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 case if __name__ == '__main__': str1 = 'abcabcaa' str2 = 'acbacba' prinlAllLCSSorted(str1 str2) # This code is contributed by mohit kumar 29 
C#
// 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[MAXMAX];     // 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] = '';   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 
JavaScript
<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(str1str2len1len2ij)  {  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(str1str2len1len2dataindx1indx2currlcs)  {  // if currlcs is equal to lcslen then print it  if (currlcs == lcslen)  {  data[currlcs] = null;  document.write(data.join('')+'  
'
); 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(str1str2) { // 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>

Producción
ababa abaca abcba acaba acaca acbaa acbca

Complejidad del tiempo: O(m*n*p) donde 'm' es la longitud de la matriz de caracteres 'n' es la longitud de la matriz1 y 'p' es la longitud de la matriz2.
Complejidad espacial: O(m*n) porque estamos usando una matriz 2D de tamaño m*n para almacenar el resultado.