实现前缀树

问题描述:给定一个字符串数组,判断这个数组中是否包含某一个字符串word,或判断这个数组是否包含前缀prefix
暴力的实现方法是将给定的字符串wordprefix与字符串数组一一比对,查找到了则返回true,否则返回false。这种情况下的时间复杂度为 O ( ∣ S ∣ n ) O(\lvert S \rvert n) O(Sn),空间复杂度 O ( ∣ T ∣ ) O(\lvert T \rvert) O(T)。其中 ∣ S ∣ \lvert S \rvert S代表给定字符串长度, n n n代表数组长度, ∣ T ∣ \lvert T \rvert T是字符串数组出现字符的总长度。

前缀树实现方式:时间复杂度为 O ( ∣ S ∣ ) O(\lvert S \rvert) O(S)。空间复杂度 O ( ∣ T ∣ ∣ Σ ∣ ) O(\lvert T \rvert \lvert \Sigma \rvert) O(TΣ)。其中 ∣ Σ ∣ \lvert \Sigma \rvert Σ是字符集长度。
实现 Trie (前缀树)
对于Trie树中的任意一个节点都包含一个长度为 ∣ Σ ∣ \lvert \Sigma \rvert Σ的节点数组,和一个isEnd代表当前节点是否是某个单词的末尾的下一个节点Trie树中的每个节点不一定只代表一个字符。Trie树中的每个节点都只有唯一一个父节点(根节点无父节点)

以下给出了Trie树构建的示例,一开始只有node1节点并且node1的所有位置都为null

  1. 插入一个单词app
    ①新建node2并将node1a位置指向node2
    ②新建node3并将node2p位置指向node3
    ③新建node4并将node3p位置指向node4
    node4isEnd为设为true
  2. 插入一个单词apa
    ①新建node5并将node3a位置指向node5
    node5isEnd设为true
  3. 插入一个单词appa
    ①新建node6并将node4a位置指向node6
    node6isEnd设为true
  4. 查找apa
    node1a位置指向node2
    node2p位置指向node3
    node3a位置指向node5
    node5isEndtrue,代表存在这样的单词。

(下面图片展示了插入appapa后的字典树)
字典树示例

class Trie {
    private Trie[] tree;
    private boolean isEnd;
    public Trie() {
        tree = new Trie[26];
        isEnd = false;
    }

    public void insert(String word) {
        char[] chs = word.toCharArray();
        Trie pr = this;
        for (int i = 0; i < chs.length; i++) {
            int ch = chs[i] - 'a';
            if (pr.tree[ch] == null) {
                pr.tree[ch] = new Trie();
            }
            pr = pr.tree[ch];
        }
        pr.isEnd = true;
    }

    public boolean search(String word) {
        Trie pr = findTrie(word);
        return pr != null && pr.isEnd;
    }

    public boolean startsWith(String prefix) {
        return findTrie(prefix) != null;
    } 
    //查找word的下一个节点,如果word='ap',那么上面的例子中就找到node3
    public Trie findTrie(String word) {
        char[] chs = word.toCharArray();
        Trie pr = this;
        for (int i = 0; i < chs.length; i++) {
            int ch = chs[i] - 'a';
            if (pr.tree[ch] == null) return null;
            pr = pr.tree[ch];
        }
        return pr;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值