140. 单词拆分 II

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

说明:

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/word-break-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

字典树

import java.util.*;

class Solution {

    private Trie trie;
    
    private List<String> ans = new ArrayList<>();

    private LinkedList<String> item = new LinkedList<>();

    private void addToAns() {
        ans.add(String.join(" ", item));
    }

    private void solve(String s, int index) {
        if (index == s.length()) {
            addToAns();
            return;
        }
        Trie.Node cur = trie.getRoot();
        for (int i = index; i < s.length(); ++i) {
            char path = s.charAt(i);
            Trie.Node child = cur.children.get(path);
            if (child == null) {
                return;
            }
            if (child.end) {
                item.offerLast(s.substring(index, i + 1));
                solve(s, i + 1);
                item.pollLast();
            }
            cur = child;
        }
    }

    public List<String> wordBreak(String s, List<String> wordDict) {
        this.trie = new Trie();
        this.trie.insert(wordDict);
        solve(s, 0);
        return ans;
    }
}

class Trie {

    private Node root = new Node();

    class Node {
        Map<Character, Node> children = new HashMap<>();
        boolean end;
    }

    public Node getRoot() {
        return root;
    }

    public void insert(List<String> strs) {
        for (String str : strs) {
            insert(str);
        }
    }

    private void insert(String str) {
        Node cur = root;
        for (int i = 0; i < str.length(); ++i) {
            char path = str.charAt(i);
            Node child = cur.children.get(path);
            if (child == null) {
                child = new Node();
                cur.children.put(path, child);
            }
            cur = child;
        }
        cur.end = true;
    }
}

记忆化搜索

class Solution {
    public List<String> wordBreak(String s, List<String> wordDict) {
        Map<Integer, List<List<String>>> map = new HashMap<Integer, List<List<String>>>();
        List<List<String>> wordBreaks = backtrack(s, s.length(), new HashSet<String>(wordDict), 0, map);
        List<String> breakList = new LinkedList<String>();
        for (List<String> wordBreak : wordBreaks) {
            breakList.add(String.join(" ", wordBreak));
        }
        return breakList;
    }

    public List<List<String>> backtrack(String s, int length, Set<String> wordSet, int index, Map<Integer, List<List<String>>> map) {
        if (!map.containsKey(index)) {
            List<List<String>> wordBreaks = new LinkedList<List<String>>();
            if (index == length) {
                wordBreaks.add(new LinkedList<String>());
            }
            for (int i = index + 1; i <= length; i++) {
                String word = s.substring(index, i);
                if (wordSet.contains(word)) {
                    List<List<String>> nextWordBreaks = backtrack(s, length, wordSet, i, map);
                    for (List<String> nextWordBreak : nextWordBreaks) {
                        LinkedList<String> wordBreak = new LinkedList<String>(nextWordBreak);
                        wordBreak.offerFirst(word);
                        wordBreaks.add(wordBreak);
                    }
                }
            }
            map.put(index, wordBreaks);
        }
        return map.get(index);
    }
}
posted @   Tianyiya  阅读(26)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示