给你一个字符串 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
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/word-break
(个人理解,若有错误,欢迎指正,谢谢!!)
题目的意思是让一段字符串,无论怎样拆分,都可以在字典中找到相对应的字符串,且...maybe就是...可能...一段字符串在同一种分割方法时,是不可以重复分割同一段字符串, 例如:s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"],sand和dog重复了一个d,这样sand和dog就不可以同时出现在同一个分割方法中,sandog可以分成san和dog,或者sand和og;
/**
* @param {string} s
* @param {string[]} wordDict
* @return {boolean}
*/
var wordBreak = function(s, wordDict) {
let dp = Array(s.length + 1).fill(false);//令dp中全为false
dp[0] = true;
for(let i = 0; i <= s.length; i++){//使dp中的字符串值在匹配时可以改变,i代表dp的下标,s字符串可截取的长度
for(let j = 0; j < wordDict.length; j++) {//截止到i的字符串,与字典中,所有字符串进行匹配
if(i >= wordDict[j].length) {//i>=word.length保证字符串的长度够用
if(s.slice(i - wordDict[j].length, i) === wordDict[j] && dp[i - wordDict[j].length]) {
//s.slice(i,a)截取的是下标i到下标a(不包括下标a的对应字符串值),且它的字符串内容等于字典中的某个字符串
//dp[i - wordDict[j].length]的作用是,这段字符串的首字母是否为true,如果为true,那么证明在这个字符串首字母之前的字符串是可以被分割,且等于字典中的某个字符串。如果为false,那么证明这段字符串首字母前的字符串是在字典中无法匹配到的
dp[i] = true
}
}
}
}
return dp[s.length];//如果dp的最后一个字符串为true,那么证明,i走到了dp字符串的最后,且i=s.length+1;所以证明此时是判断s的最后一个字符串是否可以在字典中匹配到相应的字符串
};
里面最关键的是记录可分割的字符串的末尾的元素的下一个元素要做标记。这个标记是判断是否可以从这个字符串为起始进行分割的标记。如果这个元素并没有被标记,那么以这个元素为起始的字符串是不可以被分割的。如果这个元素被标记,那么以这个元素起始的字符串是可以被继续分割的。
因为dp的长度是比原来的字符串多了一个位置,这个位置就是判断这个字符串是否可以被分割到最后。如果原来的字符串的末尾可以被分割,那么dp[i]=true,导致dp的最后一个元素为true,证明原始的字符串是可以被全部分割的。
dp[s.length]指的是dp的最后一个元素。