Tags

  • AWS (7)
  • Apigee (3)
  • ArchLinux (5)
  • Array (6)
  • Backtracking (6)
  • BinarySearch (6)
  • C++ (19)
  • CI&CD (3)
  • Calculus (2)
  • DesignPattern (43)
  • DisasterRecovery (1)
  • Docker (8)
  • DynamicProgramming (20)
  • FileSystem (11)
  • Frontend (2)
  • FunctionalProgramming (1)
  • GCP (1)
  • Gentoo (6)
  • Git (15)
  • Golang (1)
  • Graph (10)
  • GraphQL (1)
  • Hardware (1)
  • Hash (1)
  • Kafka (1)
  • LinkedList (13)
  • Linux (27)
  • Lodash (2)
  • MacOS (3)
  • Makefile (1)
  • Map (5)
  • MathHistory (1)
  • MySQL (21)
  • Neovim (10)
  • Network (66)
  • Nginx (6)
  • Node.js (33)
  • OpenGL (6)
  • PriorityQueue (1)
  • ProgrammingLanguage (9)
  • Python (10)
  • RealAnalysis (20)
  • Recursion (3)
  • Redis (1)
  • RegularExpression (1)
  • Ruby (19)
  • SQLite (1)
  • Sentry (3)
  • Set (4)
  • Shell (3)
  • SoftwareEngineering (12)
  • Sorting (2)
  • Stack (4)
  • String (2)
  • SystemDesign (13)
  • Terraform (2)
  • Tree (24)
  • Trie (2)
  • TwoPointers (16)
  • TypeScript (3)
  • Ubuntu (4)
  • Home

    [Dynamic Programming] Count Construct

    Published Nov 12, 2021 [  DynamicProgramming  ]

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

    The function should return the number of ways that the target can be constructed by concatenating elements of the wordBank array.

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

    Brute Force

    const countConstruct = (target, wordBank) => {
    	// base case
    	// if the target is empty, we have 1 way to construct it
    	if (target === '') return 1;
    
    	let totalCount = 0;
    
    	for(let word of wordBank) {
    		if(target.startsWith(word)) {
    			let remainCount = countConstruct(target.slice(word.length), wordBank)
    			totalCount += remainCount;
    		}
    	}
    
    	return totalCount
    }
    

    Memoization

    const countConstructMemo = (target, wordBank, memo = {}) => {
    	if(target in memo) return memo[target]
    	// base case
    	// if the target is empty, we have 1 way to construct it
    	if (target === '') return 1;
    
    	let totalCount = 0;
    
    	for(let word of wordBank) {
    		if(target.startsWith(word)) {
    			let remainCount = countConstructMemo(target.slice(word.length), wordBank, memo)
    			totalCount += remainCount;
    		}
    	}
    
    	memo[target] = totalCount
    	return totalCount
    }
    

    Tabulation

    const countConstructTab = (target, wordBank) => {
    	let table = Array(target.length + 1).fill(0)
    	table[0] = 1;
    
    	for (let i = 0; i <= target.length; i++) {
    		if(table[i]) {
    			for(let word of wordBank) {
    				if(target.slice(i, i + word.length) === word) {
    					table[i + word.length] += table[i]
    				}
    			}
    		}
    	}
    
    	return table[target.length]
    }
    

    Reference