今天要看的是 Trie tree。
字典樹(trie tree)如下圖所示,擁有相同前綴的單字也會共享部分路徑,然後在出現差異的部分開始分岔出去。因此搜尋時從上往下走,如果走到某一部找不到相關的內容,就表示該元素不存在。

圖片出處:維基百科
208. Implement Trie (Prefix Tree) 這題是基本的實作題,單純把 trie 刻出來就可以了。特別需要留意的是,當一個單字結束時,要特別打上 tag 來做辨識,例如我們先加入了 apple 這個單字,如果這時候要搜 app,由於走到最後時找不到 tag,因此就可以判斷該單字不存在。
另外,下面的實作方法是單字的每個 char 都開一個 dict 往下。其實有想過在初期時,是不是可以直接把整個單字(或者部分單字)當成 key(像上圖所示),等到出現了有相同 prefix 的單字後才去做 merge。不過這麼做要不停的 detect & merge,不確定是否能有更好的效能,複雜度也更高因此最後沒有採用。
class Trie:
    def __init__(self):
        self.d = {}
    def insert(self, word: str) -> None:
        d = self.d
        for i in word:
            if i in d:
                d = d[i]
            else:
                d[i] = {}
                d = d[i]
        d[1] = 1
    def search(self, word: str) -> bool:
        d = self.d
        for i in word:
            if len(d) == 0:
                return False
            if i not in d:
                return False
            d = d[i]
        return True if 1 in d else False
    def startsWith(self, prefix: str) -> bool:
        d = self.d
        for i in prefix:
            if len(d) == 0:
                return False
            if i not in d:
                return False
            d = d[i]
        return True