https://leetcode-cn.com/problems/word-break/

这道题是要你判断能不能分解,我们给它扩展一下,求分解的方法数

动态规划

  1. // 深度优先
  2. // s[0......index-1]这一段,已经分解过了,不用在操心
  3. // s[index.....] 这一段字符串,能够被分解的方法数,返回
  4. public boolean wordBreak(String s, List<String> wordDict) {
  5. return dfs(s, 0, new HashSet<>(wordDict)) != 0;
  6. }
  7. public int dfs(String s, int index, HashSet<String> wordDict) {
  8. if (index == s.length()) {
  9. return 1;
  10. }
  11. int ways = 0;
  12. for (int end = index; end < s.length(); end++) {
  13. if (wordDict.contains(s.substring(index, end + 1))) {
  14. ways += dfs(s, end + 1, wordDict);
  15. }
  16. }
  17. return ways;
  18. }
  1. // 动态规划
  2. public boolean wordBreak2(String s, List<String> wordDict) {
  3. Set<String> set = new HashSet<>(wordDict);
  4. int N = s.length();
  5. int[] dp = new int[N + 1];
  6. dp[N] = 1;
  7. for (int index = N - 1; index >= 0; index--) {
  8. int ways = 0;
  9. for (int end = index; end < N; end++) {
  10. if (set.contains(s.substring(index, end + 1))) {
  11. ways += dp[end + 1];
  12. }
  13. }
  14. dp[index] = ways;
  15. }
  16. return dp[0] != 0;
  17. }

时间复杂度O(N^3)

优化

最里面的枚举怎么优化?(去hashset里查,样本量不大的情况看成是O(1), 样本量过大的话就是O(N))
image.png
构建前缀树
image.png

因此现在我每次验证都是O(1)的,
然后前缀树还能帮我们剪枝, 没路了就可以break掉