Give a dictionary of words and a sentence with all whitespace removed, return the number of sentences you can form by inserting whitespaces to the sentence so that each word can be found in the dictionary.
Example 1:
Input:
“CatMat”
[“Cat”, “Mat”, “Ca”, “tM”, “at”, “C”, “Dog”, “og”, “Do”]
Output: 3
Explanation:
we can form 3 sentences, as follows:
“CatMat” = “Cat” + “Mat”
“CatMat” = “Ca” + “tM” + “at”
“CatMat” = “C” + “at” + “Mat”
Example 2:
Input:
“a”
[]
Output: 0
题目大意:
一个字符串s,被“字典集合”(wordDict)中的单词拼接而成的可能性种数。
解题思路:
这是经典题。如果知道s[0:n-1)很容易知道s[0:n)是否有解,既然和子问题有关,就用DP。
- 定义dp[i]为字符串s[0,i)是合法分解种数。
- 判断一个字符串是否可以合法分解,方案是尝试在每一位进行分解,若其中一个可分解,即有解,加入到dp[i]中。
递归式为dp[i] += dp[k] * isWord(s[k:i)), 0 <= k < i. - 方向为从左到右i=0..n, 初始值为dp[0] = 1.
注意事项:
- 将两个输入都转换成小写。
- dp[n+1]而不是dp[n],而for循环从1开始。
- 递归中dp[i]用+操作符。
Java代码:
1 | public int wordBreak3(String s, Set<String> dict) { |
算法分析:
时间复杂度为O(n2)
,空间复杂度为O(n)
。
这道题一开始走过一些弯路,首先我觉得类似于Catalan算法,左右半部都是子问题,但其实这属于单边问题。所以写了以下算法:
Java代码:
1 | public int wordBreak3_wrong(String s, Set<String> dict) { |
但这个方法会有重复解,比如
“abc”, “a”,”b”,”c”
-> dp["ab"] * dp["c"] = 1
-> dp["a"] * dp["bc"] = 1
所以解重复,因为这问题是单边子问题而不是Catalan问题。
更改版本为单边子问题,一开始用dp[n]导致初始化稍复杂,其实初始化可以并入到递归式,只要用dp[n+1]即可。
Java代码:
1 | public int wordBreak32(String s, Set<String> dict) { |