Longest Common Subsequence LCS Java | Fresher Interview
Fast recall
Quick revision
Core answer
dp[i][j] = LCS length of the first i chars of A and first j of B. If A[i-1] == B[j-1], dp[i][j] = dp[i-1][j-1] + 1; else max(dp[i-1][j], dp[i][j-1]). O(m*n) time and space.Whether you set up the 2D dp, the match vs no-match transition, and distinguish subsequence from substring
Confusing subsequence (non-contiguous) with substring (contiguous), or off-by-one with 1-indexed dp
Note the match transition uses the diagonal +1 and that LCS underlies diff tools and edit distance
Interview-ready guide
Interview answer
First I'd clarify what a subsequence is, because that's the common confusion.
A subsequence keeps the characters in their original order but allows gaps, so it doesn't have to be contiguous, unlike a substring which does. The longest common subsequence problem asks for the longest sequence that appears in both strings as a subsequence. I solve it with a two-dimensional DP table.
I define dp of i, j as the length of the LCS of the first i characters of string A and the first j characters of string B. I use one-based indexing for the table so that the base cases, an empty prefix on either side, are naturally zero. The transition has two cases.
If the current characters match, that is A at i minus one equals B at j minus one, then I extend the LCS by taking the diagonal value and adding one: dp of i minus one, j minus one, plus one.
If they don't match, I can't extend, so I take the best I can get by dropping one character from either string: the max of dp of i minus one, j and dp of i, j minus one. The answer is in dp of m, n.
The complexity is O of m times n in both time and space, though I can reduce the space to O of n by keeping only the previous row, since each cell only depends on the row above and the current row. I'd also mention that LCS is the foundation of diff tools that compare files and it's closely related to edit distance, which is another classic DP.
Longest Common Subsequence LCS Java | Fresher Interview
Direct Answer
LCS finds the longest sequence appearing in both strings in order but not necessarily contiguous. Use a 2D table where dp[i][j] = LCS length of the first i chars of A and first j of B. If A[i-1] == B[j-1], dp[i][j] = dp[i-1][j-1] + 1; else max(dp[i-1][j], dp[i][j-1]). O(m*n) time and space.
Deep Dive & Architecture
A subsequence keeps relative order but may skip characters, so it is different from a substring. The DP table answers smaller prefix questions: dp[i][j] stores the LCS length for the first i characters of the first string and the first j characters of the second.
An empty prefix has an LCS length of zero, which fills row 0 and column 0. When the current characters match, they can extend a smaller common subsequence, so use the diagonal cell plus one. When they differ, skip one current character and keep the better result from the cell above or the cell to the left.
Worked example: ABC and AC
A matches A, so that cell becomes 1. B does not match C, so the best neighboring value stays 1. Finally C matches C, so the diagonal value 1 becomes 2. The LCS is AC, with length 2.
The full table uses O(m × n) time and space. If only the length is needed, two rows are enough for O(min(m, n)) space. If the actual sequence is needed, walk backward from dp[m][n]: take matching characters, otherwise move toward the larger neighboring cell.
Code Example
int lcs(String a, String b) {
int m = a.length(), n = b.length();
int[][] dp = new int[m + 1][n + 1]; // dp[0][*]=dp[*][0]=0 (base)
for (int i = 1; i <= m; i++)
for (int j = 1; j <= n; j++) {
if (a.charAt(i-1) == b.charAt(j-1))
dp[i][j] = dp[i-1][j-1] + 1; // match: diagonal +1
else
dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]); // no match
}
return dp[m][n];
}
// a="AGGTAB", b="GXTXAYB" -> LCS "GTAB" length 4
Common Mistakes & Pitfalls
- Subsequence vs substring: LCS allows gaps; substring must be contiguous (different DP).
- Off-by-one: with 1-indexed dp, compare
a.charAt(i-1)andb.charAt(j-1). - Forgetting base row/column:
dp[0][*]anddp[*][0]are 0. - Wrong no-match transition: it's
maxof the two neighbors, not the diagonal.
Check your understanding
Answer these without looking back at the article.
- What is dynamic programming and when do you use it?
- What is memoization vs tabulation in DP and which should you use in interviews?
- How do you solve the coin change problem using dynamic programming?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.