My Learning Blog

DP-1143 - 2/25/2024

use dfs with memo and dp table

One using memoization (top-down approach) and the other using dynamic programming (bottom-up approach).I prefer the DP method.

function longestCommonSubsequence(text1: string, text2: string): number {
    // A cache to remember solutions to subproblems we've already solved
    const memo = new Map<string, number>();

    // A recursive helper function to find LCS length for substrings up to indices i and j
    function dfs(i: number, j: number): number {
        // Base case: if either string is fully traversed, return 0
        if (i < 0 || j < 0) return 0;

        // Generate a unique key to identify the current state (subproblem)
        const key = `${i},${j}`;
        // If this problem was already solved, return the stored result
        if (memo.has(key)) return memo.get(key)!;

        let result = 0;
        // If characters at current positions are the same, move diagonally and add 1
        if (text1[i] === text2[j]) {
            result = dfs(i - 1, j - 1) + 1;
        } else {
            // Otherwise, try moving in either string and choose the max result
            result = Math.max(dfs(i - 1, j), dfs(i, j - 1));
        }

        // Store the result in the cache before returning
        memo.set(key, result);
        return result;
    }

    // Start the recursion from the end of both strings
    return dfs(text1.length - 1, text2.length - 1);
};


function longestCommonSubsequence(text1: string, text2: string): number {
    // n and m store the lengths of text1 and text2, respectively
    const n: number = text1.length, m: number = text2.length;

    // Initialize a 2D array f with dimensions (n+1) x (m+1), filled with 0s
    // This array will store the lengths of LCS for different pairs of prefixes of text1 and text2
    const f: number[][] = Array.from({length: n + 1}, () => Array(m + 1).fill(0));

    // Iterate over each character of text1 (i) and text2 (j)
    for (let i = 0; i < n; i++) {
        for (let j = 0; j < m; j++) {
            // If characters at current positions in both strings match
            if (text1[i] === text2[j]) {
                // Update the current cell with the value from the top-left cell plus one
                f[i + 1][j + 1] = f[i][j] + 1;
            } else {
                // If they don't match, take the maximum value from the cell above or to the left
                f[i + 1][j + 1] = Math.max(f[i][j + 1], f[i + 1][j]);
            }
        }
    }

    // Return the bottom-right cell of the array, which contains the length of LCS
    return f[n][m];
};