The Longest Common Subsequence (LCS) problem involves finding the longest subsequence that is common to two given sequences. Unlike substrings, the characters in a subsequence do not need to be contiguous but must maintain their relative order.
Algorithm Explanation
The LCS can be efficiently solved using dynamic programming:
-
Dynamic Programming Table: Create a 2D array
dp
wheredp[i][j]
represents the length of the longest common subsequence of the firsti
characters ofstr1
and the firstj
characters ofstr2
. -
Initialization: Initialize the first row and the first column of the table to 0, since the LCS of any string with an empty string is 0.
-
Filling the DP Table:
- Loop through each character in both strings.
- If the characters match (
str1[i-1] == str2[j-1]
), thendp[i][j] = dp[i-1][j-1] + 1
. - If they do not match, take the maximum value from the left or above:
dp[i][j] = Math.Max(dp[i-1][j], dp[i][j-1])
.
-
Result: The value in
dp[m][n]
(wherem
andn
are the lengths of the two strings) will be the length of the longest common subsequence.
C# Implementation
Here’s how you can implement the LCS problem in C#:
using System;
class Program
{
static void Main()
{
string str1 = "AGGTAB";
string str2 = "GXTXAYB";
int result = LongestCommonSubsequence(str1, str2);
Console.WriteLine("Length of Longest Common Subsequence: " + result);
}
static int LongestCommonSubsequence(string str1, string str2)
{
int m = str1.Length;
int n = str2.Length;
int[,] dp = new int[m + 1, n + 1]; // DP table to store lengths
// Fill the DP table
for (int i = 1; i <= m; i++)
{
for (int j = 1; j <= n; j++)
{
// Check for matching characters
if (str1[i - 1] == str2[j - 1])
{
dp[i, j] = dp[i - 1, j - 1] + 1; // Increment length
}
else
{
dp[i, j] = Math.Max(dp[i - 1, j], dp[i, j - 1]); // Max from left or above
}
}
}
return dp[m, n]; // Return the length of the longest common subsequence
}
}
Explanation of Code
- Input: The program defines two strings,
str1
andstr2
, for which it will find the longest common subsequence. - LongestCommonSubsequence Function:
- Initializes a 2D array
dp
with dimensions(m + 1) x (n + 1)
, wherem
andn
are the lengths ofstr1
andstr2
, respectively.
- Initializes a 2D array
- Filling the DP Table:
- The outer loop iterates through the characters of
str1
, and the inner loop iterates through the characters ofstr2
. - When a match is found, it increments the LCS length stored in
dp[i, j]
. - If the characters do not match, it takes the maximum length from either the left (
dp[i, j - 1]
) or above (dp[i - 1, j]
).
- The outer loop iterates through the characters of
- Return Result: The function returns
dp[m, n]
, which contains the length of the longest common subsequence.
Complexity
- Time Complexity: O(m * n), where
m
is the length ofstr1
andn
is the length ofstr2
. This arises from filling out the DP table using nested loops. - Space Complexity: O(m * n) for the
dp
table.
Space Optimization
While the above approach is straightforward, it can be optimized to O(n) in space complexity by only keeping track of the current and previous rows of the DP table, as only the last row and the current row are needed at any point in time.
Summary
This dynamic programming approach efficiently computes the length of the longest common subsequence between two strings, balancing clarity and performance for practical input sizes.