A Space Optimized Solution of LCS

01 Jul, 2022
Given two strings, find the length of the longest subsequence present in both of them.  
Examples: 
LCS for input Sequences “ABCDGH” and “AEDFHR” is “ADH” of length 3. 
LCS for input Sequences “AGGTAB” and “GXTXAYB” is “GTAB” of length 4.
We have discussed a typical dynamic programming-based solution for LCS. We can optimize the space used by LCS problem. We know the recurrence relationship of the LCS problem is 
CPP
Java
C#
Javascript
/* Returns length of LCS for X[0..m-1], Y[0..n-1] */int lcs(string &X, string &Y){    int m = X.length(), n = Y.length();    int L[m+1][n+1];     /* Following steps build L[m+1][n+1] in bottom up       fashion. Note that L[i][j] contains length of       LCS of X[0..i-1] and Y[0..j-1] */    for (int i=0; i<=m; i++)    {        for (int j=0; j<=n; j++)        {            if (i == 0 || j == 0)                L[i][j] = 0;             else if (X[i-1] == Y[j-1])                L[i][j] = L[i-1][j-1] + 1;             else                L[i][j] = max(L[i-1][j], L[i][j-1]);        }    }     /* L[m][n] contains length of LCS for X[0..n-1] and       Y[0..m-1] */    return L[m][n];}
class GFG {     // Returns length of LCS for X[0..m-1], Y[0..n-1]     public static int lcs(String X, String Y)    {         // Find lengths of two strings        int m = X.length(), n = Y.length();         int L[][] = new int[m + 1][n + 1];         /* Following steps build L[m+1][n+1] in bottom up        fashion. Note that L[i][j] contains length of        LCS of X[0..i-1] and Y[0..j-1] */         for (int i = 0; i <= m; i++) {            for (int j = 0; j <= n; j++) {                if (i == 0 || j == 0)                    L[i][j] = 0;                 else if (X[i - 1] == Y[j - 1])                    L[i][j] = L[i - 1][j - 1] + 1;                 else                    L[i][j] = max(L[i - 1][j], L[i][j - 1]);            }        }         /* L[m][n] contains length of LCS for X[0..n-1] and           Y[0..m-1] */        return L[m][n];    }} // This code is contributed by rajsanghavi9.
// C# program to implement// the above approachusing System; class GFG{   // Returns length of LCS for X[0..m-1], Y[0..n-1]  public static int lcs(string X, string Y)  {     // Find lengths of two strings    int m = X.Length, n = Y.Length;     int[,] L = new int[m + 1, n + 1];     /* Following steps build L[m+1][n+1] in bottom up        fashion. Note that L[i][j] contains length of        LCS of X[0..i-1] and Y[0..j-1] */     for (int i = 0; i <= m; i++) {      for (int j = 0; j <= n; j++) {        if (i == 0 || j == 0)          L[i, j] = 0;         else if (X[i - 1] == Y[j - 1])          L[i, j] = L[i - 1, j - 1] + 1;         else          L[i, j] = Math.Max(L[i - 1, j], L[i, j - 1]);      }    }     /* L[m][n] contains length of LCS for X[0..n-1] and           Y[0..m-1] */    return L[m, n];  } } // this code is contributed by code_hunt.
<script> // Dynamic Programming Java implementation of LCS problem // Utility function to get max of 2 integersfunction max(a, b){    if (a > b)        return a;    else        return b;} // Returns length of LCS for X[0..m-1], Y[0..n-1]function lcs(X, Y, m, n){    var L = new Array(m + 1);    for(var i = 0; i < L.length; i++)    {        L[i] = new Array(n + 1);    }    var i, j;         /* Following steps build L[m+1][n+1] in    bottom up fashion. Note that L[i][j]    contains length of LCS of X[0..i-1]    and Y[0..j-1] */    for(i = 0; i <= m; i++)    {        for(j = 0; j <= n; j++)        {            if (i == 0 || j == 0)                L[i][j] = 0;            else if (X[i - 1] == Y[j - 1])                L[i][j] = L[i - 1][j - 1] + 1;            else                L[i][j] = max(L[i - 1][j], L[i][j - 1]);        }    }         /* L[m][n] contains length of LCS    for X[0..n-1] and Y[0..m-1] */    return L[m][n];} // This code is contributed by akshitsaxenaa09.</script>
How to find the length of LCS is O(n) auxiliary space?
We strongly recommend that you click here and practice it, before moving on to the solution.One important observation in the above simple implementation is, in each iteration of the outer loop we only need values from all columns of the previous row. So there is no need to store all rows in our DP matrix, we can just store two rows at a time and use them. In that way, used space will be reduced from L[m+1][n+1] to L[2][n+1]. Below is the implementation of the above idea. 
C++
Java
Python3
C#
PHP
Javascript
// Space optimized C++ implementation// of LCS problem#include<bits/stdc++.h>using namespace std; // Returns length of LCS// for X[0..m-1], Y[0..n-1]int lcs(string &X, string &Y){         // Find lengths of two strings    int m = X.length(), n = Y.length();     int L[2][n + 1];     // Binary index, used to    // index current row and    // previous row.    bool bi;     for (int i = 0; i <= m; i++)    {                 // Compute current        // binary index        bi = i & 1;         for (int j = 0; j <= n; j++)        {            if (i == 0 || j == 0)                L[bi][j] = 0;             else if (X[i-1] == Y[j-1])                 L[bi][j] = L[1 - bi][j - 1] + 1;             else                L[bi][j] = max(L[1 - bi][j],                               L[bi][j - 1]);        }    }     // Last filled entry contains    // length of LCS    // for X[0..n-1] and Y[0..m-1]    return L[bi][n];} // Driver codeint main(){    string X = "AGGTAB";    string Y = "GXTXAYB";     printf("Length of LCS is %d\n", lcs(X, Y));     return 0;}
// Java Code for A Space Optimized// Solution of LCS class GFG {         // Returns length of LCS    // for X[0..m - 1],    // Y[0..n - 1]    public static int lcs(String X,                          String Y)    {                 // Find lengths of two strings        int m = X.length(), n = Y.length();             int L[][] = new int[2][n+1];             // Binary index, used to index        // current row and previous row.        int bi=0;             for (int i = 0; i <= m; i++)        {                         // Compute current binary index            bi = i & 1;                 for (int j = 0; j <= n; j++)            {                if (i == 0 || j == 0)                    L[bi][j] = 0;                     else if (X.charAt(i - 1) ==                         Y.charAt(j - 1))                    L[bi][j] = L[1 - bi][j - 1] + 1;                     else                    L[bi][j] = Math.max(L[1 - bi][j],                                        L[bi][j - 1]);            }        }             // Last filled entry contains length of        // LCS for X[0..n-1] and Y[0..m-1]        return L[bi][n];    }              // Driver Code    public static void main(String[] args)    {        String X = "AGGTAB";        String Y = "GXTXAYB";             System.out.println("Length of LCS is " +                                    lcs(X, Y));    }} // This code is contributed by Arnav Kr. Mandal.
# Space optimized Python# implementation of LCS problem # Returns length of LCS for# X[0..m-1], Y[0..n-1]def lcs(X, Y):         # Find lengths of two strings    m = len(X)    n = len(Y)     L = [[0 for i in range(n+1)] for j in range(2)]     # Binary index, used to index current row and    # previous row.    bi = bool         for i in range(m):        # Compute current binary index        bi = i&1         for j in range(n+1):            if (i == 0 or j == 0):                L[bi][j] = 0             elif (X[i] == Y[j - 1]):                L[bi][j] = L[1 - bi][j - 1] + 1             else:                L[bi][j] = max(L[1 - bi][j],                               L[bi][j - 1])     # Last filled entry contains length of LCS    # for X[0..n-1] and Y[0..m-1]    return L[bi][n] # Driver CodeX = "AGGTAB"Y = "GXTXAYB" print("Length of LCS is", lcs(X, Y)) # This code is contributed by Soumen Ghosh.
// C# Code for A Space// Optimized Solution of LCSusing System; class GFG{         // Returns length of LCS    // for X[0..m - 1],    // Y[0..n - 1]    public static int lcs(string X,                          string Y)    {                 // Find lengths of        // two strings        int m = X.Length, n = Y.Length;             int [,]L = new int[2, n + 1];             // Binary index, used to        // index current row and        // previous row.        int bi = 0;             for (int i = 0; i <= m; i++)        {                         // Compute current            // binary index            bi = i & 1;                 for (int j = 0; j <= n; j++)            {                if (i == 0 || j == 0)                    L[bi, j] = 0;                      else if (X[i - 1] == Y[j - 1])                    L[bi, j] = L[1 - bi,                                 j - 1] + 1;                     else                    L[bi, j] = Math.Max(L[1 - bi, j],                                        L[bi, j - 1]);            }        }             // Last filled entry contains        // length of LCS for X[0..n-1]        // and Y[0..m-1]        return L[bi, n];    }         // Driver Code    public static void Main()    {        string X = "AGGTAB";        string Y = "GXTXAYB";             Console.Write("Length of LCS is " +                                lcs(X, Y));    }} // This code is contributed// by shiv_bhakt.
<?php// Space optimized PHP implementation// of LCS problem // Returns length of LCS// for X[0..m-1], Y[0..n-1]function lcs($X, $Y){         // Find lengths of two strings    $m = strlen($X);    $n = strlen($Y);     $L = array(array());     // Binary index, used to index    // current row and previous row.    for ($i = 0; $i <= $m; $i++)    {                 // Compute current binary index        $bi = $i & 1;         for ($j = 0; $j <= $n; $j++)        {            if ($i == 0 || $j == 0)                $L[$bi][$j] = 0;             else if ($X[$i - 1] == $Y[$j - 1])                $L[$bi][$j] = $L[1 - $bi][$j - 1] + 1;             else                $L[$bi][$j] = max($L[1 - $bi][$j],                                  $L[$bi][$j - 1]);        }    }     // Last filled entry contains    // length of LCS    // for X[0..n-1] and Y[0..m-1]    return $L[$bi][$n];} // Driver code$X = "AGGTAB";$Y = "GXTXAYB"; echo "Length of LCS is : ",               lcs($X, $Y); // This code is contributed by Ryuga?>
<script>    // Javascript Code for A Space Optimized Solution of LCS         // Returns length of LCS    // for X[0..m - 1],    // Y[0..n - 1]    function lcs(X, Y)    {                   // Find lengths of two strings        let m = X.length, n = Y.length;               let L = new Array(2);        for (let i = 0; i < 2; i++)        {            L[i] = new Array(n + 1);            for (let j = 0; j < n + 1; j++)            {                L[i][j] = 0;            }        }                        // Binary index, used to index        // current row and previous row.        let bi=0;               for (let i = 0; i <= m; i++)        {                           // Compute current binary index            bi = i & 1;                   for (let j = 0; j <= n; j++)            {                if (i == 0 || j == 0)                    L[bi][j] = 0;                       else if (X[i - 1] ==                         Y[j - 1])                    L[bi][j] = L[1 - bi][j - 1] + 1;                       else                    L[bi][j] = Math.max(L[1 - bi][j],                                        L[bi][j - 1]);            }        }               // Last filled entry contains length of        // LCS for X[0..n-1] and Y[0..m-1]        return L[bi][n];    }         let X = "AGGTAB";    let Y = "GXTXAYB";     document.write("Length of LCS is " +                       lcs(X, Y)); </script>
Length of LCS is 4

Time Complexity : O(m*n) Auxiliary Space : O(n)
This article is contributed Shivam Mittal. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.
We can further improve the space complexity of above program
Python3
Java
def lcs(text1, text2):    m, n = len(text1), len(text2)    if m > n : text1, text2 = text2, text1    dp = [0] * (n + 1)    for c in text1:        prev = 0        for i, d in enumerate(text2):            prev, dp[i + 1] = dp[i + 1], prev + 1 if c == d else max(dp[i], dp[i + 1])    return dp[-1]X = "AGGTAB"Y = "GXTXAYB"  print("Length of LCS is", lcs(X, Y))
/*package whatever //do not write package name here */class GFG {    public static int lcs(String text1, String text2) {        int[] dp = new int[text2.length()+1];        for(int i = 0; i< text1.length(); i++){            int prev = dp[0];            for(int j = 1; j < dp.length; j++){                int temp = dp[j];                if(text1.charAt(i) != text2.charAt(j-1)){                    dp[j] = Math.max(dp[j-1], dp[j]);                }else{                    dp[j] = prev +1;                }                prev = temp;            }        }        return dp[dp.length-1];    }      public static void main(String[] args)    {        String X = "AGGTAB";        String Y = "GXTXAYB";              System.out.println("Length of LCS is " + lcs(X, Y));    }}
Length of LCS is 4

 
Vishal_Khoda
ankthon
divyeshrabadiya07
rajsanghavi9
akshitsaxenaa09
code_hunt
tusharkhera1
LCS
subsequence
Dynamic Programming
Dynamic Programming
LCS
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Find if there is a path between two vertices in an undirected graph
Count number of binary strings without consecutive 1's
Optimal Substructure Property in Dynamic Programming | DP-2
Find if a string is interleaved of two other strings | DP-33
Maximum sum such that no two elements are adjacent
How to solve a Dynamic Programming Problem ?
Word Break Problem | DP-32
Maximum profit by buying and selling a share at most twice
Unique paths in a Grid with Obstacles
Palindrome Partitioning | DP-17