美文网首页
算法笔记之字典树——连接词

算法笔记之字典树——连接词

作者: 简单一点点 | 来源:发表于2021-12-15 14:21 被阅读0次

又是一个字典树(trie)问题,其实字典树的思路不难想到,但是本体的细节很巧妙,而且一些用例比较阴间,需要注意的地方多。

题目描述

LeetCode472. 连接词

给你一个 不含重复 单词的字符串数组 words ,请你找出并返回 words 中的所有 连接词 。

连接词 定义为:一个完全由给定数组中的至少两个较短单词组成的字符串。

解题思路

主要思路:

  • 匹配字符串问题,首先明确要使用字典树。
  • 先把words按照单词长度排序,再依次遍历,线查找每个单词是否连接词,然后在插入。这样的好处是不用担心搜索到的单词是它自身。
  • 查找的时候需要使用DFS。
  • 同时利用记忆化搜索优化效率。

需要注意的一点就是要考虑空字符串这种阴间场景。

Java代码

class Solution {
    private TrieNode root;
    private Map<String, Boolean> memo;
    public List<String> findAllConcatenatedWordsInADict(String[] words) {
        Arrays.sort(words, (a, b) -> (a.length() - b.length()));
        root = new TrieNode(0);
        List<String> r = new ArrayList<>();
        memo = new HashMap<>();
        for(int i = 0; i < words.length; i++) {
            if(words[i].length() == 0) { // 跳过空串
                continue;
            }   
            // 先查找
            if(search(words[i], root, 0)) {               
                r.add(words[i]);
            }
            // 这里要注意,单词插入后,记忆化哈希表中一定是true,
            memo.put(words[i], true);
            // 在插入
            add(words[i], root);
        }
        return r;
        
    }

    // 字典树
    class TrieNode {
        public TrieNode[] next;
        public boolean isEnd;
        public int current; // 这个没啥用
        public TrieNode(int current) {
            this.current = current;
            this.next = new TrieNode[26];
        }
    }

    // 向字典树中插入单词
    private void add(String word, TrieNode trie) {
        TrieNode node = trie;
        for(int i = 0; i < word.length(); i++) {
            int c = word.charAt(i) - 'a';
            if(node.next[c] == null) {
                node.next[c] = new TrieNode(c);                
            } 
            node = node.next[c];           
        }
        node.isEnd = true;
    }

    // 在字典树中搜索单词 dfs
    private boolean search(String word, TrieNode trie, int start) {
        if(start == word.length()) {
            if(trie.isEnd) {
                return true;
            } 
            return false;
        }
        int c = word.charAt(start) - 'a';
        if(trie.next[c] == null) {
            return false;
        }
        TrieNode nextNode = trie.next[c];
        // 考虑下一字符属于新单词的场景
        if(nextNode.isEnd) {
            // 只有从开头开始的单词才加入记忆化哈希表
            String now = word.substring(start +1);
            boolean flag = false;
            if(memo.containsKey(now)) {
                flag = memo.get(now);
            } else {
                flag = search(word, root, start + 1);
                memo.put(now, flag);
            }
            
            if(flag) {
                return true;
            }
        }
        boolean f = search(word, nextNode, start + 1);
        return f;
    }
}

相关文章

  • 算法笔记之字典树——连接词

    又是一个字典树(trie)问题,其实字典树的思路不难想到,但是本体的细节很巧妙,而且一些用例比较阴间,需要注意的地...

  • 大厂算法面试之leetcode精讲22.字典树

    大厂算法面试之leetcode精讲22.字典树 视频讲解(高效学习):点击学习[https://xiaochen1...

  • 数据结构之字典树Trie

    字典树Trie 字典树也叫前缀树,是一种在字符串查找,前缀匹配等问题广泛应用的算法,为什么使用字典树呢?我们都知道...

  • 算法导论:字典树

    算法导论:字典树 如果我们给定字符串集合为{b abc abd bcd abcd efg ...

  • 实现字典树

    题目:实现字典树 (算法课第七课) Trie树,又称为字典树、单词查找树或者前缀树,是一种用于快速检索的多叉数结构...

  • 字典树

    功能 字典树是用数组存储大量字符串的一种算法 字典树算法开辟空间非常大,但是对于字符串插入和查询有很快的速度 用法...

  • AskMe Spring项目提问功能——前缀树敏感词过滤

    问题发布功能的重点在于如何实现敏感词过滤,基本的算法是前缀树算法,前缀树也就是字典树,通过前缀树匹配可以加快敏感词...

  • Swift 算法实战二(二叉树、二分搜索)

    Swift 算法实战一(集合,字典,链表,栈,队列等算法) Swift 算法实战二(二叉树、二分搜索) 前言 这是...

  • Swift 算法实战一(集合,字典,链表,栈,队列等算法)

    Swift 算法实战一(集合,字典,链表,栈,队列等算法) Swift 算法实战二(二叉树、二分搜索) 前言 用 ...

  • 字典序算法笔记

    一、相关概念介绍 字典序字典序就是按照字典中出现的顺序对字符进行排序。 全排列给定多个字符,可以按照任意顺序进行排...

网友评论

      本文标题:算法笔记之字典树——连接词

      本文链接:https://www.haomeiwen.com/subject/ckpefrtx.html