You are given a string target, an array of strings words, and an integer array costs, both arrays of the same length.
Imagine an empty string s.
You can perform the following operation any number of times (including zero):
i in the range [0, words.length - 1].words[i] to s.costs[i].Return the minimum cost to make s equal to target. If it's not possible, return -1.
Example 1:
Input: target = "abcdef", words = ["abdef","abc","d","def","ef"], costs = [100,1,1,10,5]
Output: 7
Explanation:
The minimum cost can be achieved by performing the following operations:
"abc" to s at a cost of 1, resulting in s = "abc"."d" to s at a cost of 1, resulting in s = "abcd"."ef" to s at a cost of 5, resulting in s = "abcdef".Example 2:
Input: target = "aaaa", words = ["z","zz","zzz"], costs = [1,10,100]
Output: -1
Explanation:
It is impossible to make s equal to target, so we return -1.
Constraints:
1 <= target.length <= 20001 <= words.length == costs.length <= 501 <= words[i].length <= target.lengthtarget and words[i] consist only of lowercase English letters.1 <= costs[i] <= 105Problem Overview: You are given a target string and a list of words where each word has an associated cost. The task is to construct the target by concatenating words from the list while minimizing the total cost. Words can only match the target at valid positions, so the core challenge is choosing the cheapest sequence of matches that fully builds the string.
Approach 1: Brute Force Backtracking (Exponential Time, O(2^n) time, O(n) space)
The most direct idea is to try constructing the target from left to right. At every index, iterate through every word and check whether it matches the substring starting at that position. If it matches, recursively attempt to build the rest of the string and add the word's cost. This explores every possible combination of word placements. While conceptually simple, repeated exploration of the same suffix makes this approach exponential and impractical for larger inputs.
Approach 2: Dynamic Programming with Substring Checks (O(n * m * L) time, O(n) space)
Dynamic programming avoids recomputation by storing the minimum cost needed to construct the suffix starting at each index. For position i, iterate over all words and check whether each word matches the substring starting at i. If it does, update dp[i] using cost(word) + dp[i + len(word)]. This eliminates repeated work compared to brute force, but still performs many substring comparisons, especially when the word list is large.
Approach 3: Trie + Memoized DFS (Optimal) (O(n * L) time, O(n + totalTrieNodes) space)
The optimized solution stores all words in a Trie. Starting from each index of the target, traverse the Trie character by character while simultaneously scanning the string. Every time a Trie node marks the end of a word, treat it as a valid cut and recursively compute the cost for the remaining suffix. Use memoization to cache the minimum cost for each starting index so each suffix is solved once. Trie traversal avoids checking every word individually and only follows characters that actually match the target. The recursion behaves like a DFS over valid word boundaries while memoization guarantees efficiency.
Recommended for interviews: The Trie + memoized DFS approach is the expected solution. Brute force demonstrates the baseline idea of exploring word placements, but the optimal approach shows you understand prefix structures and dynamic programming to eliminate redundant work. Interviewers typically look for recognizing overlapping subproblems and using a Trie to efficiently match prefixes.
We first create a Trie trie, where each node in the Trie contains an array children of length 26, and each element in the array is a pointer to the next node. Each node in the Trie also contains a cost variable, which represents the minimum cost from the root node to the current node.
We traverse the words array, inserting each word into the Trie while updating the cost variable for each node.
Next, we define a memoized search function dfs(i), which represents the minimum cost to construct the string starting from target[i]. The answer is dfs(0).
The calculation process of the function dfs(i) is as follows:
i geq len(target), it means the entire string has been constructed, so return 0.trie and traverse all suffixes starting from target[i], finding the minimum cost, which is the cost variable in the trie, plus the result of dfs(j+1), where j is the ending position of the suffix starting from target[i].Finally, if dfs(0) < inf, return dfs(0); otherwise, return -1.
The time complexity is O(n^2 + L), and the space complexity is O(n + L). Here, n is the length of target, and L is the sum of the lengths of all words in the words array.
Python
Java
C++
Go
TypeScript
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Brute Force Backtracking | O(2^n) | O(n) | Conceptual starting point or very small inputs |
| Dynamic Programming with Substring Checks | O(n * m * L) | O(n) | When word list is small and substring checks are cheap |
| Trie + Memoized DFS | O(n * L) | O(n + Trie) | General case with many words and shared prefixes |
Most Asked FAANG Coding Question! | Longest Common Prefix - Leetcode 14 • Greg Hogg • 123,655 views views
Watch 9 more video solutions →Practice Construct String with Minimum Cost (Easy) with our built-in code editor and test cases.
Practice on FleetCodePractice this problem
Open in Editor