1. 程式人生 > >Trie樹,加快單詞查詢效率

Trie樹,加快單詞查詢效率

為了提高我的單詞查詢的速度,我拜讀了@Rshcaroline的程式碼,發現trie樹是一個很好解決這個問題的方法

Trie樹,又叫字典樹、字首樹(Prefix Tree)、單詞查詢樹 或 鍵樹,是一種多叉樹結構

Trie樹的基本性質:

  1. 根節點不包含字元,除根節點外的每一個子節點都包含一個字元。
  2. 從根節點到某一個節點,路徑上經過的字元連線起來,為該節點對應的字串。
  3. 每個節點的所有子節點包含的字元互不相同。 通常在實現的時候,會在節點結構中設定一個標誌,用來標記該結點處是否構成一個單詞(關鍵字)。

一下是我的程式碼

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))