前缀树

前缀树的构造

什么是Trie树

Trie树,即字典树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:最大限度地减少无谓的字符串比较,查询效率比哈希表高。

Trie的核心思想是空间换时间。利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。

它有3个基本性质:

  • 根节点不包含字符,除根节点外每一个节点都只包含一个字符。
  • 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。
  • 每个节点的所有子节点包含的字符都不相同。

构建Trie树

好比假设有b,abc,abd,bcd,abcd,efg,hii 这6个单词,我们构建的树就是如下图这样的:

在这里插入图片描述
如上图所示,对于每一个节点,从根遍历到他的过程就是一个单词,如果这个节点被标记为红色,就表示这个单词存在,否则不存在。

Leetcode例题

力扣208:实现一个 Trie (前缀树),包含 insert, search, 和 startsWith 这三个操作。

class Trie:
    def __init__(self):
        self.lookup = {}
        
    def insert(self, word: str) -> None:
    #构造前缀树
        tree = self.lookup
        for a in word:
            if a not in tree:
                tree[a] = {}
            tree = tree[a]
        tree['#'] = '#'

    def search(self, word: str) -> bool:
        tree = self.lookup
        for a in word:
            if a not in tree:
                return False
            tree = tree[a]
        return '#' in tree

    def startsWith(self, prefix: str) -> bool:
        tree = self.lookup
        for a in prefix:
            if a not in tree:
                return False
            tree = tree[a]
        return True

在这里插入图片描述
思路就是把所有的words构造一个前缀树,例如words = [“oath”,“pea”,“eat”,“rain”]。则构造出来的前缀树是{'o': {'a': {'t': {'h': {'end': '1'}}}}, 'p': {'e': {'a': {'end': '1'}}}, 'e': {'a': {'t': {'end': '1'}}}, 'r': {'a': {'i': {'n': {'end': '1'}}}}}
只要遍历给定的数组然后dfs就可以了。
例如从矩阵的‘o’开始时,先判断‘o’是否在trie中,如果不在就退出。如果在,那么trie = trie[‘o’]。trie[‘o’] = {‘a’: {‘t’: {‘h’: {‘end’: ‘1’}}}。下面dfs试探四周的字母,即‘a’和‘e’,之后的过程和之前一样。当遇到’end’的时候,说明找到了一个符合的单词,此时把他加入res,并且把trie[‘end’]更改,以免重复访问。代码如下

class Solution:
    def findWords(self, board: List[List[str]], words: List[str]) -> List[str]:
		#构造前缀树
        trie = {}
        for word in words:
            t = trie
            for a in word:
                if a not in t:
                    t[a] = {}
                t = t[a]
            t['end'] = '1'
        res = []
        row = len(board)
        col = len(board[0])
		
		#dfs递归试探
        def dfs(i,j,trie,s):
            c = board[i][j]
            if c not in trie:return
            trie = trie[c]
            if 'end' in trie and trie['end']=='1':
                res.append(s+c)
                #防止重复访问
                trie['end'] = '0'
            board[i][j] = '#'
            for x,y in [[-1,0],[0,-1],[1,0],[0,1]]:
                tmp_i = i+x
                tmp_j = j+y
                if 0<=tmp_i<row and 0<=tmp_j<col and board[tmp_i][tmp_j]!='#':
                    dfs(tmp_i,tmp_j,trie,s+c)
            board[i][j] = c
        
        for i in range(row):
            for j in range(col):
                dfs(i,j,trie,'')
        return res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值