题目
给你一个字符串
s和一个字符串列表wordDict作为字典。请你判断是否可以利用字典中出现的单词拼接出s。
输入: s = "applepenapple", wordDict = ["apple", "pen"]
输出: true
解释: 返回 true 因为 "applepenapple" 可以由 "apple" "pen" "apple" 拼接成。
注意,你可以重复使用字典中的单词。
题解
第一种
首先,定义一个长度为len的数组dp,用于记录字符串s的前i个字符能否被拆分成若干个在字典中出现过的单词。接下来遍历字符串s的前i个字符,假设当前处理到了第i个字符,则:如果s的前i个字符是一个在字典中出现过的单词,则令dp[i]为true。如果s的前i个字符不是一个在字典中出现过的单词,则需要分别考虑以第j个字符为结尾、第i个字符为开头的子串subCur,其中j的范围从0到i。对于每个子串subCur,只有当subCur是一个在字典中出现过的单词,且dp[j-1]为true,即s的前j-1个字符可以被拆分成若干个在字典中出现过的单词,才能令dp[i]为true。最终返回dp[len-1]的值,即整个字符串s是否可以被拆分成若干个在字典中出现过的单词
var wordBreak = function (s, wordDict) {
let len = s.length
let dp = new Array(len).fill(false)
for (let i = 0; i < len; i++) {
let cur = s.substring(0, i + 1)
if (wordDict.indexOf(cur)>-1) {
dp[i] = true
} else {
for (let j = 0; j <= i; j++) {
let subCur = s.substring(j, i + 1)
dp[i] = dp[i] || (wordDict.indexOf(subCur)>-1 && dp[j - 1])
}
}
}
return dp[len - 1]
};
第二种
定义一个长度为 n+1 的数组 dp,其中 dp[i] 表示前 i 个字符是否可以拆分成 wordDict 中的单词。首先要将 wordDict 转化为一个 Set,方便后面的查找操作。初始化 dp[0] 为 true,因为空字符串肯定可以由 wordDict 中的单词组成。接下来是动态转移方程,对于每一个 i,都在从 0 到 i-1 的范围内进行循环。如果 dp[j] 为 true,且 s 的子串从 j 开始、长度为 i-j 的子串也在 wordDict 中出现,则将 dp[i] 设为 true 并跳出内层循环,因为已经找到一种拆分方案了。最后返回 dp[n] 即可,表示整个字符串是否可以被拆分成 wordDict 中的单词
var wordBreak = function(s, wordDict) {
const n = s.length;
const wordDictSet = new Set(wordDict);
const dp = new Array(n+1).fill(false);
dp[0] = true;
for(let i = 1;i<=n;i++){
for(let j = 0;j<i;j++){
if(dp[j] && wordDictSet.has(s.substr(j,i-j))){
dp[i] = true;
break;
}
}
}
return dp[n];
};
坚持努力,无惧未来!