fn lcs_length(s1: &str, s2: &str) -> usize { let m = s1.len(); let n = s2.len(); let s1_bytes = s1.as_bytes(); let s2_bytes = s2.as_bytes(); let mut dp = vec![vec![0; n + 1]; m + 1]; for i in 1..=m { for j in 1..=n { if s1_bytes[i - 1] == s2_bytes[j - 1] { dp[i][j] = dp[i - 1][j - 1] + 1; } else { dp[i][j] = dp[i - 1][j].max(dp[i][j - 1]); } } } dp[m][n] } fn main() { let s1 = "AGGTAB"; let s2 = "GXTXAYB"; println!("{}", lcs_length(s1, s2)); }
The longest common subsequence between "AGGTAB" and "GXTXAYB" is "GTAB" which has length 4.
The code returns 4, so option C is correct.
fn lcs_sequence(s1: &str, s2: &str) -> String { let m = s1.len(); let n = s2.len(); let s1_bytes = s1.as_bytes(); let s2_bytes = s2.as_bytes(); let mut dp = vec![vec![0; n + 1]; m + 1]; for i in 1..=m { for j in 1..=n { if s1_bytes[i - 1] == s2_bytes[j - 1] { dp[i][j] = dp[i - 1][j - 1] + 1; } else { dp[i][j] = dp[i - 1][j].max(dp[i][j - 1]); } } } let mut i = m; let mut j = n; let mut lcs = Vec::new(); while i > 0 && j > 0 { if s1_bytes[i - 1] == s2_bytes[j - 1] { lcs.push(s1_bytes[i - 1]); i -= 1; j -= 1; } else if dp[i - 1][j] > dp[i][j - 1] { i -= 1; } else { j -= 1; } } lcs.reverse(); String::from_utf8(lcs).unwrap() } fn main() { let s1 = "ABCBDAB"; let s2 = "BDCABA"; println!("{}", lcs_sequence(s1, s2)); }
The longest common subsequence between "ABCBDAB" and "BDCABA" is "BDAB".
The code reconstructs this sequence by backtracking the dp table.
fn lcs_length(s1: &str, s2: &str) -> usize { let m = s1.len(); let n = s2.len(); let s1_bytes = s1.as_bytes(); let s2_bytes = s2.as_bytes(); let mut dp = vec![vec![0; n]; m]; for i in 1..m { for j in 1..n { if s1_bytes[i] == s2_bytes[j] { dp[i][j] = dp[i - 1][j - 1] + 1; } else { dp[i][j] = dp[i - 1][j].max(dp[i][j - 1]); } } } dp[m - 1][n - 1] } fn main() { let s1 = "ABC"; let s2 = "AC"; println!("{}", lcs_length(s1, s2)); }
The dp table must be sized (m+1) x (n+1) to handle base cases and avoid index errors.
Initializing dp with m x n causes out-of-bound accesses when i or j equals m or n.
The DP solution uses a 2D table of size m x n and fills each cell once.
Thus, the time complexity is O(m * n).
fn lcs_length(s1: &str, s2: &str) -> usize { let m = s1.len(); let n = s2.len(); let s1_bytes = s1.as_bytes(); let s2_bytes = s2.as_bytes(); let mut dp = vec![vec![0; n + 1]; m + 1]; for i in 1..=m { for j in 1..=n { if s1_bytes[i - 1] == s2_bytes[j - 1] { dp[i][j] = dp[i - 1][j - 1] + 1; } else { dp[i][j] = dp[i - 1][j].max(dp[i][j - 1]); } } } dp[m][n] } fn main() { // Which call is correct? }
Option A uses valid DNA sequences with only 'A', 'C', 'G', 'T'.
Option A contains invalid characters 'X', 'Y', 'Z'.
Option A contains 'N' which is not standard DNA base here.
Option A uses lowercase letters which differ from uppercase ASCII codes.
