单词拆分

题目

给你一个字符串 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

思路

class Solution {
public:
    bool wordBreak(string s, vector<string>& wordDict) {
        //首先这是一个完全背包的问题,因为每一个单词都可以选择多次
        //wordDict数组内部的每一个单词就是物品,物品的重量就是单词的长度,背包就是字符串s的长度

        /*dp数组的含义,dp[j]表示字符串长度是j的时候,是否可以拆成数组内部的每一个单词的组合
          dp[j] 可以是true或者false
        */
        /*dp数组的递推公式,运用共是确定的一般方法可以这样看:
          如果最后一个单词是wordDict[i], 那么dp[j] = dp[j - wordDict[i].size()]  ,其他的情况都是假的
          以此类推
        */
        //dp数组的初始化,dp[0]是没有意义的,但是为了推导公式,它必须是dp[0] = true;

        //为了方便查找建立的集合
        unordered_set<string> wordDictmap(wordDict.begin(), wordDict.end());

        int bsize = s.size();
        vector<int> dp(bsize + 1, false);
        dp[0] = true;
        //求的是排列数,因为需要在意前后的顺序
        for(int j = 1; j <= bsize; j++) {//遍历背包的大小
            for(int i = 0; i < j; i++) { //
                //因为这里要看s[j - i]是不是存在于s中,所以我们可以用哈希表
                string substr = s.substr(i, j - i);
                if(wordDictmap.find(substr) != wordDictmap.end() && dp[i]) {
                    dp[j] = true;
                }
            }
        }
        return dp[bsize];
    }
};
posted @ 2023-07-08 17:43  铜锣湾陈昊男  阅读(7)  评论(0)    收藏  举报