139. 单词拆分

139. 单词拆分

题目链接:139. 单词拆分(中等)

给你一个字符串 s 和一个字符串列表 wordDict 作为字典。请你判断是否可以利用字典中出现的单词拼接出 s

注意:不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。

示例 1:

输入: s = "leetcode", wordDict = ["leet", "code"]
输出: true
解释: 返回 true 因为 "leetcode" 可以由 "leet" 和 "code" 拼接成。

示例 2:

输入: s = "applepenapple", wordDict = ["apple", "pen"]
输出: true
解释: 返回 true 因为 "applepenapple" 可以由 "apple" "pen" "apple" 拼接成。
    注意,你可以重复使用字典中的单词。

示例 3:

输入: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]
输出: false

提示:

  • 1 <= s.length <= 300

  • 1 <= wordDict.length <= 1000

  • 1 <= wordDict[i].length <= 20

  • swordDict[i] 仅有小写英文字母组成

  • wordDict 中的所有字符串 互不相同

解题思路

题目中说明字典中的单词可以重复使用,并且目的是能不能拼成给定的字符串,所以这是一个完全背包问题。

wordDict就是物品,字符串s就是背包容量,题目问单词能否拼成字符串s,其实就是物品能不能把背包装满。

1、定义dp数组

dp[i] : 字符串s的前i个字符组成的字符串s[0,i-1]能否被拆分成若干个字典中出现的单词。

2、确定状态转移方程

dp[i]之前就下面这些状态: dp[i-1],dp[i-2],...,dp[i-k],... ,但是与哪个状态有关?

dp[i]只与dp[i-k] ,记为dp[j]有关系,其中k为s[i:j]的长度。

我们假设: s[0:i] 字串对应dp[i+1],它是否为true取决于两点:

它的前缀字串s[0:j-1]的dp[j],是否为true 剩余字串s[j:i],是否在单词列表里。 3、边界条件 如果字符串为空的话,说明出现在字典里。虽然看似荒谬,但是这只是为了让边界的情况也能套用状态转移方程而已。 dp[0] = true;

4、确定dp数组的计算顺序

一维dp数组解决完全背包问题,求组合问题先正序遍历物品,再正序遍历背包。求排列问题先正序遍历背包,再正序遍历物品。针对本题采用后者更容易写。

C++

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 s1 = s.substr(j, i - j);
                if (dp[j] && (wordSet.find(s1) != wordSet.end())) {
                    dp[i] = true;
                }
            }
        }
        return dp[s.size()];
    }
};

JavaScript

/**
 * @param {string} s
 * @param {string[]} wordDict
 * @return {boolean}
 */
var wordBreak = function(s, wordDict) {
    const dp = new Array(s.length + 1).fill(false);
    dp[0] = true;
    for (let i = 1; i <= s.length; i++) {
        for (let j = 0; j < i; j++) {
            let s1 = s.slice(j, i);
            if (dp[j] && wordDict.find(obj => obj == s1)) {
                dp[i] = true;
            }
        }
    }
    return dp[s.length];
};

 

posted @ 2022-03-07 21:40  wltree  阅读(133)  评论(0编辑  收藏  举报