Given two strings s1 and s2, the task is to find the length of longest common subsequence present in both of them.

**Examples:**

Input:s1 = “ABCDGH”, s2 = “AEDFHR”

Output:3

LCS for input Sequences “AGGTAB” and “GXTXAYB” is “GTAB” of length 4.

Input:s1 = “striver”, s2 = “raj”

Output:1

The **naive solution** for this problem is to generate all subsequences of both given sequences and find the longest matching subsequence. This solution is exponential in term of time complexity. The general recursive solution of the problem is to generate all subsequences of both given sequences and find the longest matching subsequence. Total possible combinations will be 2^{n}. Hence recursive solution will take **O(2 ^{n})**.

**Optimal Substructure:**

- Let the input sequences be X[0..m-1] and Y[0..n-1] of lengths m and n respectively. And let L(X[0..m-1], Y[0..n-1]) be the length of LCS of the two sequences X and Y. Following is the recursive definition of L(X[0..m-1], Y[0..n-1]).
- If last characters of both sequences match (or X[m-1] == Y[n-1]) then L(X[0..m-1], Y[0..n-1]) = 1 + L(X[0..m-2], Y[0..n-2])
- If last characters of both sequences do not match (or X[m-1] != Y[n-1]) then L(X[0..m-1], Y[0..n-1]) = MAX ( L(X[0..m-2], Y[0..n-1]), L(X[0..m-1], Y[0..n-2])

Given below is the recursive solution to the LCS problem:

## C++

`// A Naive C++ recursive implementation ` `// of LCS of two strings ` `#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, ` `int` `m, ` `int` `n) ` `{ ` ` ` `if` `(m == 0 || n == 0) ` ` ` `return` `0; ` ` ` ` ` `if` `(X[m - 1] == Y[n - 1]) ` ` ` `return` `1 + lcs(X, Y, m - 1, n - 1); ` ` ` `else` ` ` `return` `max(lcs(X, Y, m, n - 1), ` ` ` `lcs(X, Y, m - 1, n)); ` `} ` ` ` `// Driver Code ` `int` `main() ` `{ ` ` ` `string X = ` `"AGGTAB"` `; ` ` ` `string Y = ` `"GXTXAYB"` `; ` ` ` ` ` `// Find the length of string ` ` ` `int` `m = X.length(); ` ` ` `int` `n = Y.length(); ` ` ` ` ` `cout << ` `"Length of LCS: "` `<< lcs(X, Y, m, n); ` ` ` ` ` `return` `0; ` `} ` |

*chevron_right*

*filter_none*

## Java

`// A Naive Java recursive implementation ` `// of LCS of two strings ` ` ` `class` `GFG { ` ` ` `// Returns length of LCS for X[0..m-1], Y[0..n-1] ` ` ` `static` `int` `lcs(String X, String Y, ` `int` `m, ` `int` `n) { ` ` ` `if` `(m == ` `0` `|| n == ` `0` `) { ` ` ` `return` `0` `; ` ` ` `} ` ` ` ` ` `if` `(X.charAt(m - ` `1` `) == Y.charAt(n - ` `1` `)) { ` ` ` `return` `1` `+ lcs(X, Y, m - ` `1` `, n - ` `1` `); ` ` ` `} ` `else` `{ ` ` ` `return` `Math.max(lcs(X, Y, m, n - ` `1` `), ` ` ` `lcs(X, Y, m - ` `1` `, n)); ` ` ` `} ` ` ` `} ` `// Driver Code ` ` ` ` ` `public` `static` `void` `main(String[] args) { ` ` ` `String X = ` `"AGGTAB"` `; ` ` ` `String Y = ` `"GXTXAYB"` `; ` ` ` ` ` `// Find the length of String ` ` ` `int` `m = X.length(); ` ` ` `int` `n = Y.length(); ` ` ` `System.out.println(` `"Length of LCS: "` `+ lcs(X, Y, m, n)); ` ` ` ` ` `} ` `} ` ` ` `// This code is contributed by 29AjayKumar ` |

*chevron_right*

*filter_none*

## Python3

`# A Naive Python recursive implementation ` `# of LCS of two strings ` ` ` `# Returns length of LCS for X[0..m-1], Y[0..n-1] ` `def` `lcs(X, Y, m, n): ` ` ` `if` `(m ` `=` `=` `0` `or` `n ` `=` `=` `0` `): ` ` ` `return` `0` ` ` ` ` `if` `(X[m ` `-` `1` `] ` `=` `=` `Y[n ` `-` `1` `]): ` ` ` `return` `1` `+` `lcs(X, Y, m ` `-` `1` `, n ` `-` `1` `) ` ` ` `else` `: ` ` ` `return` `max` `(lcs(X, Y, m, n ` `-` `1` `), ` ` ` `lcs(X, Y, m ` `-` `1` `, n)) ` ` ` `# Driver Code ` `if` `__name__ ` `=` `=` `'__main__'` `: ` ` ` `X ` `=` `"AGGTAB"` ` ` `Y ` `=` `"GXTXAYB"` ` ` ` ` `# Find the length of string ` ` ` `m ` `=` `len` `(X) ` ` ` `n ` `=` `len` `(Y) ` ` ` ` ` `print` `(` `"Length of LCS:"` `, ` ` ` `lcs(X, Y, m, n)) ` ` ` `# This code is contributed by 29AjayKumar ` |

*chevron_right*

*filter_none*

## C#

`// A Naive recursive C#implementation of ` `// LCS of two strings ` `using` `System; ` ` ` `class` `GFG ` `{ ` ` ` `// Returns length of LCS for ` `// X[0..m-1], Y[0..n-1] ` `static` `int` `lcs(String X, String Y, ` ` ` `int` `m, ` `int` `n) ` `{ ` ` ` `if` `(m == 0 || n == 0) ` ` ` `{ ` ` ` `return` `0; ` ` ` `} ` ` ` ` ` `if` `(X[m - 1] == Y[n - 1]) ` ` ` `{ ` ` ` `return` `1 + lcs(X, Y, m - 1, n - 1); ` ` ` `} ` `else` `{ ` ` ` `return` `Math.Max(lcs(X, Y, m, n - 1), ` ` ` `lcs(X, Y, m - 1, n)); ` ` ` `} ` `} ` ` ` `// Driver Code ` `public` `static` `void` `Main() ` `{ ` ` ` `String X = ` `"AGGTAB"` `; ` ` ` `String Y = ` `"GXTXAYB"` `; ` ` ` ` ` `// Find the length of String ` ` ` `int` `m = X.Length; ` ` ` `int` `n = Y.Length; ` ` ` `Console.Write(` `"Length of LCS: "` `+ ` ` ` `lcs(X, Y, m, n)); ` `} ` `} ` ` ` `// This code is contributed by 29AjayKumar ` |

*chevron_right*

*filter_none*

## PHP

**Output:**

Length of LCS: 4

**Dynamic Programming using Memoization**

Considering the above implementation, the following is a partial recursion tree for input strings* “AXYT”* and *“AYZX”*

lcs("AXYT", "AYZX") / \ lcs("AXY", "AYZX") lcs("AXYT", "AYZ") / \ / \ lcs("AX", "AYZX") lcs("AXY", "AYZ") lcs("AXY", "AYZ") lcs("AXYT", "AY")

In the above partial recursion tree, **lcs(“AXY”, “AYZ”) is being solved twice**. On drawing the complete recursion tree, it has been observed that there are many subproblems which are solved again and again. So this problem has **Overlapping Substructure** property and recomputation of same subproblems can be avoided by either using **Memoization** or **Tabulation**. The tabulation method has been discussed here.

A common point of observation to use **memoization **in the recursive code will be the **two non-constant arguments M and N **in every function call. The function has 4 arguments, but 2 arguments are constant which do not affect the Memoization. The repetitive calls occur for N and M which have been called previously. Following the below steps will help us to write the DP solution using memoization.

- Use a 2-D array to store the computed
**lcs(m, n) value at arr[m-1][n-1]**as the string index starts from 0. - Whenever the function with the same argument m and n are called again, do not perform any further recursive call and return
*arr[m-1][n-1]*as the previous computation of the lcs(m, n) has already been stored in*arr[m-1][n-1]*, hence reducing the recursive calls that happen more then once.

Below is the implementation of the above approach:

## C++

`// C++ program to memoize ` `// recursive implementation of LCS problem ` `#include <bits/stdc++.h> ` `using` `namespace` `std; ` ` ` `const` `int` `maximum = 1000; ` ` ` `// Returns length of LCS for X[0..m-1], Y[0..n-1] */ ` `// memoization applied in recursive solution ` `int` `lcs(string X, string Y, ` `int` `m, ` `int` `n, ` `int` `dp[][maximum]) ` `{ ` ` ` `// base case ` ` ` `if` `(m == 0 || n == 0) ` ` ` `return` `0; ` ` ` ` ` `// if the same state has already been ` ` ` `// computed ` ` ` `if` `(dp[m - 1][n - 1] != -1) ` ` ` `return` `dp[m - 1][n - 1]; ` ` ` ` ` `// if equal, then we store the value of the ` ` ` `// function call ` ` ` `if` `(X[m - 1] == Y[n - 1]) { ` ` ` ` ` `// store it in arr to avoid further repetitive ` ` ` `// work in future function calls ` ` ` `dp[m - 1][n - 1] = 1 + lcs(X, Y, m - 1, n - 1, dp); ` ` ` ` ` `return` `dp[m - 1][n - 1]; ` ` ` `} ` ` ` `else` `{ ` ` ` ` ` `// store it in arr to avoid further repetitive ` ` ` `// work in future function calls ` ` ` `dp[m - 1][n - 1] = max(lcs(X, Y, m, n - 1, dp), ` ` ` `lcs(X, Y, m - 1, n, dp)); ` ` ` ` ` `return` `dp[m - 1][n - 1]; ` ` ` `} ` `} ` ` ` `// Driver Code ` `int` `main() ` `{ ` ` ` ` ` `string X = ` `"AGGTAB"` `; ` ` ` `string Y = ` `"GXTXAYB"` `; ` ` ` `int` `m = X.length(); ` ` ` `int` `n = Y.length(); ` ` ` ` ` `int` `dp[m][maximum]; ` ` ` ` ` `// assign -1 to all positions ` ` ` `memset` `(dp, -1, ` `sizeof` `(dp)); ` ` ` ` ` `cout << ` `"Length of LCS: "` `<< lcs(X, Y, m, n, dp); ` ` ` ` ` `return` `0; ` `} ` |

*chevron_right*

*filter_none*

## Java

`import` `java.util.Arrays; ` ` ` `// Java program to memoize ` `// recursive implementation of LCS problem ` `class` `GFG { ` ` ` ` ` `static` `final` `int` `maximum = ` `1000` `; ` ` ` `// Returns length of LCS for X[0..m-1], Y[0..n-1] */ ` `// memoization applied in recursive solution ` ` ` `static` `int` `lcs(String X, String Y, ` `int` `m, ` `int` `n, ` `int` `dp[][]) { ` ` ` `// base case ` ` ` `if` `(m == ` `0` `|| n == ` `0` `) { ` ` ` `return` `0` `; ` ` ` `} ` ` ` ` ` `// if the same state has already been ` ` ` `// computed ` ` ` `if` `(dp[m - ` `1` `][n - ` `1` `] != -` `1` `) { ` ` ` `return` `dp[m - ` `1` `][n - ` `1` `]; ` ` ` `} ` ` ` ` ` `// if equal, then we store the value of the ` ` ` `// function call ` ` ` `if` `(X.charAt(m - ` `1` `) == Y.charAt(n - ` `1` `)) { ` ` ` ` ` `// store it in arr to avoid further repetitive ` ` ` `// work in future function calls ` ` ` `dp[m - ` `1` `][n - ` `1` `] = ` `1` `+ lcs(X, Y, m - ` `1` `, n - ` `1` `, dp); ` ` ` ` ` `return` `dp[m - ` `1` `][n - ` `1` `]; ` ` ` `} ` `else` `{ ` ` ` ` ` `// store it in arr to avoid further repetitive ` ` ` `// work in future function calls ` ` ` `dp[m - ` `1` `][n - ` `1` `] = Math.max(lcs(X, Y, m, n - ` `1` `, dp), ` ` ` `lcs(X, Y, m - ` `1` `, n, dp)); ` ` ` ` ` `return` `dp[m - ` `1` `][n - ` `1` `]; ` ` ` `} ` ` ` `} ` ` ` `// Driver Code ` ` ` `public` `static` `void` `main(String[] args) { ` ` ` `String X = ` `"AGGTAB"` `; ` ` ` `String Y = ` `"GXTXAYB"` `; ` ` ` `int` `m = X.length(); ` ` ` `int` `n = Y.length(); ` ` ` ` ` `int` `dp[][] = ` `new` `int` `[m][maximum]; ` ` ` ` ` `// assign -1 to all positions ` ` ` `for` `(` `int` `[] row : dp) { ` ` ` `Arrays.fill(row, -` `1` `); ` ` ` `} ` ` ` ` ` `System.out.println(` `"Length of LCS: "` `+ lcs(X, Y, m, n, dp)); ` ` ` `} ` `} ` `/* This Java code is contributed by 29AjayKumar*/` |

*chevron_right*

*filter_none*

**Output:**

Length of LCS: 4

**Time Complexity:** O(N * M), where N and M is length of the first and second string respectively.

**Auxiliary Space:** (N * M)

## Recommended Posts:

- Longest Common Subsequence | DP-4
- Printing Longest Common Subsequence
- Longest Common Subsequence with at most k changes allowed
- LCS (Longest Common Subsequence) of three strings
- Longest Common Anagram Subsequence
- C++ Program for Longest Common Subsequence
- Longest Common Increasing Subsequence (LCS + LIS)
- Longest common anagram subsequence from N strings
- Edit distance and LCS (Longest Common Subsequence)
- Length of longest common subsequence containing vowels
- Longest common subsequence with permutations allowed
- Java Program for Longest Common Subsequence
- Python Program for Longest Common Subsequence
- Minimum cost to make Longest Common Subsequence of length k
- Printing Longest Common Subsequence | Set 2 (Printing All)

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.