Trie树,加快单词查找效率

原文链接
为了提高我的单词查找的速度,我拜读了@Rshcaroline的代码,发现trie树是一个很好解决这个问题的方法

Trie树,又叫字典树、前缀树(Prefix Tree)、单词查找树 或 键树,是一种多叉树结构

Trie树的基本性质:

  1. 根节点不包含字符,除根节点外的每一个子节点都包含一个字符。
  2. 从根节点到某一个节点,路径上经过的字符连接起来,为该节点对应的字符串。
  3. 每个节点的所有子节点包含的字符互不相同。
    通常在实现的时候,会在节点结构中设置一个标志,用来标记该结点处是否构成一个单词(关键字)。

为了了解它的实现,我从leetcode中找了题目Implement Trie (Prefix Tree)做了一下

一下是我的代码

class Trie:

    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.root = {}
        self.END = "$"

    def insert(self, word):
        """
        Inserts a word into the trie.
        :type word: str
        :rtype: void
        """
        t = self.root
        for c in word:
            if c not in t:
                t[c] = {}
            t = t[c]                
        t[self.END] = {}        

    def search(self, word):
        """1
        Returns if the word is in the trie.
        :type word: str
        :rtype: bool
        """
        t = self.root
        for c in word:
            if c not in t:
                return False
            else:
                t = t[c]    
        if self.END not in t:
            return False
        return True

    def startsWith(self, prefix):
        """
        Returns if there is any word in the trie that starts with the given prefix.
        :type prefix: str
        :rtype: bool
        """
        t = self.root
        for c in prefix:
            if c not in t:
                return False
            else:
                t = t[c]
        return True

对于一个单词的查找一定编辑距离的相关集合的代码如下(from @Rshcaroline),其中的deque是python的高性能双向队列,用于将trie, word, path, edit_distance整个打包起来加入队列, 广度优先查找符合的单词

def get_candidate(trie, word, edit_distance=1):
    que = deque([(trie, word, '', edit_distance)])
    while que:
        trie, word, path, edit_distance = que.popleft()
        if word == '':
            if END in trie:
                yield path
            # 词尾增加字母
            if edit_distance > 0:
                for k in trie:
                    if k != END:
                        que.appendleft((trie[k], '', path+k, edit_distance-1))
        else:
            if word[0] in trie:
                # 首字母匹配成功
                que.appendleft((trie[word[0]], word[1:], path+word[0], edit_distance))
            # 无论首字母是否匹配成功,都如下处理
            if edit_distance > 0:
                edit_distance -= 1
                for k in trie.keys() - {word[0], END}:
                    # 用k替换余词首字母,进入trie[k]
                    que.append((trie[k], word[1:], path+k, edit_distance))
                    # 用k作为增加的首字母,进入trie[k]
                    que.append((trie[k], word, path+k, edit_distance))
                # 删除目标词首字母,保持所处结点位置trie
                que.append((trie, word[1:], path, edit_distance))
                # 交换目标词前两个字母,保持所处结点位置trie
                if len(word) > 1:
                    que.append((trie, word[1]+word[0]+word[2:], path, edit_distance))
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值