You are given a string s
and a list of strings wordDict
as a dictionary. Please judge whether it can be spliced using words that appear in the dictionary s
.
Note: It is not required to use all the words that appear in the dictionary, and words in the dictionary can be used repeatedly.
Example 1:
Input: s = "leetcode", wordDict = ["leet", "code"] Output: true Explanation: Return true because "leetcode" can be spliced into "leet" and "code".
Example 2:
Input: s = "applepenapple", wordDict = ["apple", "pen"] Output: true Explanation: Return true because "applepenapple" can be spliced into "apple" "pen" "apple". Note that you can reuse words from the dictionary.
Example 3:
输入: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"] 输出: false
>>Think and analyze
This question can be violently searched using the backtracking algorithm , which is to violently search for various segmentation situations, and then determine whether it appears in this dictionary. But in this article we mainly use a complete backpack to solve the problem.
First of all, to analyze this question, let us split the word and ask whether it appears in the wordDict dictionary . Then can we think about it the other way around? In fact, there are these words in this dictionary , and ask us if we can form this string s , right? Then this string s can be understood as a container or a backpack , and these words are an item . The question turned into whether these items can exactly fill the backpack. At this time, I found that it was a bit like a backpack-type problem. Each item here can be used multiple times , such as this apple, so this is a complete backpack type problem. In this question, these items can be used unlimited times. Ask us if we can fill this backpack and find the number of permutations.
s = applepenapple,wordDict = ["apple","pen"]
↓ ↓ ↓ ↓ ↓
-> 1 2 1 1 2
The string s is a sequence like 1 2 1, so what we are looking for is the number of permutations. We need to traverse the backpack first, and then traverse the items.
- ① Each item can be used multiple times (complete backpack problem)
- ② Since what is sought is the number of permutations, determine the order of traversal
>>Five Steps of Dynamic Rules
1. Determine the meaning of the dp array and subscripts
dp[i]: If the string length is i, dp[i] is true, which means it can be split into one or more words that appear in the dictionary.
2. Determine the recursion formula
If it is determined that dp[j] is true, and the substring of the interval [j,i] appears in the dictionary, then dp[i] must be true. (j<i)
So the recurrence formula is
if([j,i] 这个区间的子串出现在字典里 && dp[j] == true)
dp[i] = true
3.dp array initialization
- It can be seen from the recursion formula that the state of dp[i] depends on whether dp[j] is true. Then dp[0] is the basis of recursion. dp[0] must be initialized to true, otherwise all the subsequent recursions will be false.
- dp[i] with a non-0 subscript is initialized to false. As long as it is not overwritten, it cannot be split into one or more words that appear in the dictionary.
Thinking: Does dp[0] make sense?
dp[0] means that if the string is empty, it means it appears in the dictionary, but the question says "given a non-empty string s", so i is 0 in the test data, then dp[0 ] The initial value is true just to derive the formula.
4. Determine the traversal order
This question must first traverse the backpack and then traverse the items. Here’s why:
In full backpack:
- If you want to find the number of combinations, the outer for loop traverses the items, and the inner for loop traverses the backpack.
- If you want to find the number of permutations, the outer for loop traverses the backpack, and the inner for loop traverses the items.
In s = "applepenapple", wordDict = ["apple", "pen"], "apple" and "pen" are items, so the combination of items must be "apple" + "pen" + "apple" to form" applepenapple". "apple" + "apple" + "pen" or "pen" + "apple" + "apple" are not allowed, so the order between items is emphasized.
5. Recommend dp[i] as an example
s = "leetcode",wordDict = ["leet","coded"], the dp status is as shown in the figure:
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict) {
unordered_set<string> wordSet(wordDict.begin(), wordDict.end());
vector<bool> dp(s.size() + 1, false);
dp[0] = true;
for (int i = 1; i <= s.size(); i++) { // 遍历背包
for (int j = 0; j < i; j++) { // 遍历物品
string word = s.substr(j, i - j); //substr(起始位置,截取的个数)
if (wordSet.find(word) != wordSet.end() && dp[j]) {
dp[i] = true;
}
}
}
return dp[s.size()];
}
};
- Time complexity :O(n^3), becausesubstrreturns a copy of the substring withO(n)(n here is the length of the substring)
- Space complexity :O(n)
Reference and recommended articles and videos:
Code Random Record (programmercarl.com)
Class screenshots from Code Caprice: