leetcode 140. 单词拆分 II(记忆化)

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

说明:

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

输入:
s = “catsanddog”
wordDict = [“cat”, “cats”, “and”, “sand”, “dog”]
输出:
[
“cats and dog”,
“cat sand dog”
]

代码

class Solution {
     Map<Integer,List<List<String>>> listMap=new HashMap<>();
    public List<String> wordBreak(String s, List<String> wordDict) {

        Trie trie=new Trie();
        Set<Integer> set=new HashSet<>();
        for(String c:wordDict) {
            set.add(c.length());
            trie.insert(c);
        }

        List<String> ret=new ArrayList<>(); 
        List<List<String>> resss=awordBreak(s,0,trie,set);
      for(java.util.List<String> list:resss) ret.add(String.join(" ",list));//添加空格

      return ret;

    }
    public List<List<String>> awordBreak(String s, int loc,Trie trie,Set<Integer> set) {
        if(!listMap.containsKey(loc)){
            List<List<String>> temp=new LinkedList<List<String>>();
            if(loc==s.length())
             temp.add(new ArrayList<>());

            for(int c:set)//测试字典的所有单词
            {
                if(loc+c<=s.length()){
                    String need=s.substring(loc,loc+c);
                    if(trie.search(need)){//该单词合法

                        List<List<String>> nexts=   awordBreak(s,loc+c,trie,set);//递归获取字符串后部分返回的单词序列
                        for(List<String> list:nexts)//将不同的单词序列与当前单词连接
                        {
                            LinkedList<String> next=new LinkedList<>(list);
                            next.offerFirst(need);
                            temp.add(next);
                        }
                    }
                }
            }
            listMap.put(loc,temp);
        }
        return listMap.get(loc);
    }
    class TrieNode {//字典树

        private TrieNode[] links;
        private final int  r=26;
        private boolean isEnd;
        public TrieNode() {
            this.links = new TrieNode[r];
        }
        public boolean contains(char c) {
            return links[c-'a']!=null;
        }
        public void put(char c,TrieNode node) {
            links[c-'a']=node;
        }
        public TrieNode get(char c) {
            return links[c-'a'];
        }
        public boolean isEnd() {
            return isEnd;
        }
        public void setEnd() {
            isEnd = true;
        }

    }
     class  Trie{

        private TrieNode root;

        public Trie() {
            this.root = new TrieNode();
        }
        public void insert(String s)
        {
            TrieNode cur=root;
            for(int i=0;i<s.length();i++)
            {
                if(!cur.contains(s.charAt(i)))
                {
                    cur.put(s.charAt(i),new TrieNode());
                }
                cur=cur.get(s.charAt(i));
            }
            cur.setEnd();
        }
        public boolean search(String s)
        {
            TrieNode cur=root;
            for(int i=0;i<s.length();i++)
            {
                if(cur.contains(s.charAt(i)))
                {
                    cur=cur.get(s.charAt(i));
                }else return false;

            }
            return cur.isEnd;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值