day46|● 139.单词拆分 ● 关于多重背包,你该了解这些! ● 背包问题总结篇!

139.单词拆分

Given a string s and a dictionary of strings wordDict, return true if s can be segmented into a space-separated sequence of one or more dictionary words.
Input: s = “applepenapple”, wordDict = [“apple”,“pen”]
Output: true
Explanation: Return true because “applepenapple” can be segmented as “apple pen apple”.
Note that you are allowed to reuse a dictionary word.

单词就是物品,字符串s就是背包,单词能否组成字符串s,就是问物品能不能把背包装满。

注意这里,遍历顺序是重要的,每个排列都不相同

dp[i] : 字符串长度为i的话,dp[i]表示到字符串长度i时有多少个连续word组成。

class Solution {
    public boolean wordBreak(String s, List<String> wordDict) {
        int[] dp = new int[s.length()+1];
        for (int i = 0; i < wordDict.size(); i++) {
            if (wordDict.get(i).length() <= s.length() && s.subSequence(0, wordDict.get(i).length()).equals(wordDict.get(i))){
                dp[wordDict.get(i).length()] = 1;
            }
        }
        for (int j = 0; j <= s.length(); j++) {
            for (int i = 0; i < wordDict.size(); i++) {
                if (j > wordDict.get(i).length() && dp[j-wordDict.get(i).length()] != 0 && s.subSequence(j-wordDict.get(i).length(), j).equals(wordDict.get(i))){
                    dp[j] = dp[j-wordDict.get(i).length()] + 1;
                }
            }
        }
        if (dp[dp.length-1] == 0) return false;
        return true;
    }
}

dp[i] : 字符串长度为i的话,dp[i]为true,表示可以拆分为一个或多个在字典中出现的单词。
这里的物品是wordDict中的word,dp[j]想要得到,首先基于此前的dp,看遍历的物品word是不是结尾的子字符串,是就true

class Solution {
    public boolean wordBreak(String s, List<String> wordDict) {
        boolean[] dp = new boolean[s.length()+1];
        dp[0] = true;
        for (int i = 1; i < dp.length; i++) {
            dp[i] = false;
        }
        for (int i = 1; i <= s.length(); i++) { // 遍历背包s
            for (int j = 0; j < wordDict.size(); j++) { // 遍历物品每个word,看最后相同长度的子字符串是不是wordDict中的word   
                if (i-wordDict.get(j).length() >= 0 && s.subSequence(i-wordDict.get(j).length(),i).equals(wordDict.get(j)) && dp[i-wordDict.get(j).length()]==true) {
                    dp[i] = true;
                }
            }
        }
        return dp[s.length()];
    }
}

如果确定dp[j] 是true,且 [j, i] 这个区间的子串出现在字典里,那么dp[i]一定是true。(j < i )。

class Solution {
    public boolean wordBreak(String s, List<String> wordDict) {
        boolean[] dp = new boolean[s.length()+1];
        dp[0] = true;
        for (int i = 1; i < dp.length; i++) {
            dp[i] = false;
        }
        for (int i = 1; i <= s.length(); i++) { // 遍历背包s字符串
            for (int j = 0; j < i; j++) { // 遍历物品(j-i的子字符串)
                String substr = s.substring(j, i);
                if (wordDict.contains(substr) && dp[j]==true) {
                    dp[i] = true;
                }
            }
        }
        return dp[s.length()];
    }
}

● 关于多重背包,你该了解这些!
● 背包问题总结篇!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值