leetcodealgorithms-templates7-dynamic-programming
 
 
 
// Time: O(2^(n + m)), Space: O(n + m)
function dfs(s1, s2) {
    return dfsHelper(s1, s2, 0, 0);
}
 
function dfsHelper(s1, s2, i1, i2) {
    if (i1 == s1.length || i2 == s2.length) {
        return 0;
    }
 
    if (s1.charAt(i1) == s2.charAt(i2)) {
        return 1 + dfsHelper(s1, s2, i1 + 1, i2 + 1);
    } else {
        return Math.max(dfsHelper(s1, s2, i1 + 1, i2), 
                            dfsHelper(s1, s2, i1, i2 + 1));
    }
}
 
// Time: O(n * m), Space: O(n + m)
function memoization(s1, s2) {
    const N = s1.length, M = s2.length;
    let cache = new Array(N).fill(new Array(M).fill(-1)); 
    return memoHelper(s1, s2, 0, 0, cache);
}
 
function memoHelper(s1, s2, i1, i2, cache) {
    if (i1 == s1.length || i2 == s2.length) {
        return 0;
    }
 
    if (cache[i1][i2] != -1) {
        return cache[i1][i2];
    }
 
    if (s1.charAt(i1) == s2.charAt(i2)) {
        cache[i1][i2] =  1 + memoHelper(s1, s2, i1 + 1, i2 + 1, cache);
    } else {
        cache[i1][i2] =  Math.max(memoHelper(s1, s2, i1 + 1, i2, cache), 
                                memoHelper(s1, s2, i1, i2 + 1, cache));
    }
    return cache[i1][i2];
}
 
// Time: O(n * m), Space: O(n + m)
function dp(s1, s2) {
    const N = s1.length, M = s2.length;
    let dp = new Array(N+1).fill(new Array(M+1).fill(0));;
 
    for (let i = 0; i < N; i++) {
        for (let j = 0; j < M; j++) {
            if (s1.charAt(i) == s2.charAt(j)) {
                dp[i+1][j+1] =  1 + dp[i][j];
            } else {
                dp[i+1][j+1] =  Math.max(dp[i][j+1], dp[i+1][j]);
            }
        }
    }
    return dp[N][M];
}
 
// Time: O(n * m), Space: O(m)
function optimizedDp(s1, s2) {
    const N = s1.length, M = s2.length;
    let dp = new Array(M + 1).fill(0);
 
    for (let i = 0; i < N; i++) {
        let curRow = new Array(M + 1).fill(0);
        for (let j = 0; j < M; j++) {
            if (s1.charAt(i) == s2.charAt(j)) {
                curRow[j+1] = 1 + dp[j];
            } else {
                curRow[j+1] = Math.max(dp[j + 1], curRow[j]);
            }
        }
        dp = curRow;
    }
    return dp[M];
}