leetcode-140. 单词拆分 II (字典树/dp + 回溯法) + 字节测开字典树算法题

给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,在字符串中增加空格来构建一个句子,使得句子中所有的单词都在词典中。返回所有这些可能的句子。

说明:

分隔时可以重复使用字典中的单词。
你可以假设字典中没有重复的单词。
示例 1:

输入:
s = "catsanddog"
wordDict = ["cat", "cats", "and", "sand", "dog"]
输出:
[
  "cats and dog",
  "cat sand dog"
]
示例 2:

输入:
s = "pineapplepenapple"
wordDict = ["apple", "pen", "applepen", "pine", "pineapple"]
输出:
[
  "pine apple pen apple",
  "pineapple pen apple",
  "pine applepen apple"
]
解释: 注意你可以重复使用字典中的单词。
示例 3:

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

两种思路做,第一种dp+回溯,第二种字典树+回溯。

方法一:dp+回溯法

leetcode-140. 单词拆分 II (字典树/dp + 回溯法) + 字节测开字典树算法题_第1张图片

这种思路是基于139.单词拆分 而来的,题意大概是给定的模式串能够被给定的非空单词列表wordDict拆分出来,dp的思想类似于求构成指定金额的钱币的不同组合。从前向后遍历利用一个一维数组不断更新当前金额情况下,上一次迭代的结果+当前金额减去当前钱币的大小的金额时的种类数目,状态转移为:dp[j] += dp[j-coins[i]]。那么用到单词拆分中时,dp[i]代表0~i-1长度的字符串是否能够由单词列表的单词构成(boolean),因此首先截取以i-1结尾,向前推当前单词列表长度个字符去比较,如果相同,那么就用到上面凑钱币的思想,使用dp[i] |= dp[i-len]的转移方程去更新当前状态 。

由于我们获取得dp数组代表的是前缀可被拆分的可能性,因此我们从后面开始对出现在单词列表中的单词开始进行深度优先遍历。如上图的状态(网站复制过来的),第一个递归过程只有一个节点,然后apple的前面又出现了两种拼接情况,于是这就需要我们使用一个双端队列Deque对整个递归的过程进行回溯的操作。在回溯的过程中,如果发现从尾部截取的字符串出现在单词列表中,并且出去该字符串的剩余部分字符串还可以由单词列表组成(利用上面的dp数组)的时候,就进行递归操作。

注意:使用双端队列因为是从尾部开始递归,所以根据题意,回溯的操作是需要使用一个头插的容器来辅助的。


你可能感兴趣的:(字典树,leetcode之路)