Published on

[Dynamic Programming] All Construct

Problem

Write a function allConstruct(target, wordBank) that accepts a target string and an array of strings

The function should return a 2D array containing all of the ways that the target can be constructed by concatenating elements of the wordBank array. Each element of the 2D array should represent on combination that constructs the target.

You may reuse elements of wordBank as many times as needed.

Brute Force

const allConstruct = (target, wordBank) => {
  // base case
  // think of the return type, it should be the same as the last return line
  if (target === '') return [[]]

  let res = []

  for (let word of wordBank) {
    if (target.startsWith(word)) {
      let remainRes = allConstruct(target.slice(word.length), wordBank)
      let temp = remainRes.map((x) => [word, ...x])
      res.push(...temp)
    }
  }

  // the return type should be the same as the base type
  return res
}

Memoization

const allConstructMemo = (target, wordBank, memo = {}) => {
  if (target in memo) return memo[target]
  // base case
  // think of the return type, it should be the same as the last return line
  if (target === '') return [[]]

  let res = []

  for (let word of wordBank) {
    if (target.startsWith(word)) {
      let remainRes = allConstructMemo(target.slice(word.length), wordBank, memo)
      let temp = remainRes.map((x) => [word, ...x])
      res.push(...temp)
    }
  }

  memo[target] = res
  // the return type should be the same as the base type
  return res
}

Tabulation

const allConstructTab = (target, wordBank) => {
  // default value & base case
  let table = Array(target.length + 1)
    .fill()
    .map((x) => [])
  console.log(table)

  for (let i = 0; i <= target.length; i++) {
    // if we can construct at table i
    if (table[i].length !== 0) {
      for (let word of wordBank) {
        if (target.slice(i, i + word.length) === word) {
          // [['a', 'b']]
          let temp = table[i].map((x) => [...x, word])
          if (i + word.length <= target.length) {
            // [['ab']]
            table[i + word.length].push(...temp)
          }
        }
      }
    }
  }

  return table[target.length]
}

Reference