Longest Common Subsequence (LCS) explained step-by-step: 2D dynamic programming grid construction, character matching rules, string reconstruction backtrack, diff algorithms, and JavaScript implementation.
The Longest Common Subsequence (LCS) problem finds the longest sequence that can be derived from two strings by deleting zero or more characters without altering the relative ordering of the remaining characters.
LCS forms the mathematical engine behind version control diff tools (like `git diff`), DNA sequence alignment in computational genomics, file comparison utilities, and speech recognition engines. By constructing an (m + 1) × (n + 1) DP table, LCS computes optimal alignment in O(m · n) time.
Create a table `dp[m+1][n+1]` filled with 0s. The extra 0th row and column handle base cases where either string is empty (length 0).
If `text1[i-1] === text2[j-1]`, extend the best previous match without either character: `dp[i][j] = 1 + dp[i-1][j-1]`.
If `text1[i-1] !== text2[j-1]`, take the maximum achievable by dropping either the current character of text1 or text2: `dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1])`.
`dp[m][n]` yields the maximum subsequence length. Backtrack from cell `(m, n)` to `(0, 0)` following the diagonal transitions to reconstruct the actual LCS string.
1function longestCommonSubsequence(text1, text2) {2 const m = text1.length;3 const n = text2.length;4 5 // Initialize (m + 1) x (n + 1) DP matrix with zeros6 const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0));7 8 // Build DP table bottom-up9 for (let i = 1; i <= m; i++) {10 for (let j = 1; j <= n; j++) {11 if (text1[i - 1] === text2[j - 1]) {12 // Characters match: take diagonal + 113 dp[i][j] = 1 + dp[i - 1][j - 1];14 } else {15 // Characters differ: take best of excluding either character16 dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);17 }18 }19 }20 21 return dp[m][n];22}23 24// Function to reconstruct the actual LCS string25function getLCSString(text1, text2) {26 const m = text1.length;27 const n = text2.length;28 const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0));29 30 for (let i = 1; i <= m; i++) {31 for (let j = 1; j <= n; j++) {32 if (text1[i - 1] === text2[j - 1]) {33 dp[i][j] = 1 + dp[i - 1][j - 1];34 } else {35 dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);36 }37 }38 }39 40 let i = m, j = n;41 const lcsChars = [];42 43 while (i > 0 && j > 0) {44 if (text1[i - 1] === text2[j - 1]) {45 lcsChars.push(text1[i - 1]);46 i--;47 j--;48 } else if (dp[i - 1][j] > dp[i][j - 1]) {49 i--;50 } else {51 j--;52 }53 }54 55 return lcsChars.reverse().join('');56}57 58// Example usage:59// longestCommonSubsequence('abcde', 'ace'); // 360// getLCSString('abcde', 'ace'); // 'ace'Play through every comparison, swap, and state change, adjust the speed, or enter custom inputs to test edge cases.
The full interactive roadmap is unlocking — these specialized modules land in upcoming releases.
This feature will be implemented in the next update.
This feature will be implemented in the next update.
This feature will be implemented in the next update.
Explore the full catalog — 30+ algorithms with more unlocking every release.
Overlapping subproblem memoization & DP table animator
Test your understanding of Longest Common Subsequence (LCS) complexity and step mechanics.
Q1.In the LCS DP table, what does the cell value dp[i][j] represent?
Q2.How can the space complexity of calculating just the LCS length (not the full string) be optimized?
Apply Longest Common Subsequence (LCS) to real coding interview questions.
Given two strings text1 and text2, return the length of their longest common subsequence.
Find minimum number of deletions to make two strings equal.