1. 程式人生 > 實用技巧 >LeetCode211. 新增與搜尋單詞 - 資料結構設計

LeetCode211. 新增與搜尋單詞 - 資料結構設計

這題和LeetCode208. 實現 Trie (字首樹)一樣,都是實現Trie樹,
支援字串的插入和查詢,只不過這裡的查詢需要支援正則表示式,也就是可以用'.'代替任何單詞,所以我們需要在查詢部分做一些修改,
插入單詞部分和208題一樣。

對於查詢單詞,由於需要支援正則表示式,所以在查詢單詞word的某個位置如果是'.'時,需要對於當前樹的所有子樹進行搜尋,因此我們
需要額外寫一個dfs函式對字串進行查詢。

這裡就在程式碼部分重點講一下dfs函式,其他部分和208題一致,可以看我上面那個連結,這裡就不細講了。

程式碼如下:

class WordDictionary {
public:
    struct Node {
        Node* son[26];
        bool is_end;
        Node() {
            for(int i = 0; i < 26; ++i) {
                son[i] = NULL;
            }
            is_end = false;
        }
    }*root;

    /** Initialize your data structure here. */
    WordDictionary() {
        root = new Node();
    }
    
    /** Adds a word into the data structure. */
    void addWord(string word) {
        Node* p = root;
        for(int i = 0; i < word.size(); ++i) {
            int u = word[i] - 'a';
            if(p -> son[u] == NULL) {
                p -> son[u] = new Node();
            }
            p = p -> son[u];
        }
        p -> is_end = true;
    }
    
    /** Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. */
    bool search(string word) {
        return dfs(root, word, 0);            //從根節點(空)開始,搜尋單詞word,第三個引數表示當前已匹配前多少個字母
    }

    bool dfs(Node* p, string &word, int i) {
        if(i == word.size()) {                        //如果所有單詞都匹配,即在trie樹中存在路徑和word相等,則需要判斷結尾的is_end標記是否為true
            return p -> is_end;
        }
        if(word[i] != '.') {                         //如果當前字母不是萬用字元'.',則不需要列舉所有可能的路徑
            int u = word[i] - 'a';
            if(p -> son[u] == NULL) {                //只需要看當前字母是否有word[i]這個兒子就好
                return false;
            }
            p = p -> son[u];                        //如果有這個兒子,繼續往下遞迴搜尋,匹配word的剩餘部分
            return dfs(p, word, i + 1);
        } else {
            for(int j = 0; j < 26; ++j) {                  //如果當前字母是萬用字元'.',則需要遞迴搜尋所有的兒子進行匹配
                if(p -> son[j] != NULL && dfs(p -> son[j], word, i + 1) == true) {      //如果沿著某個子樹匹配成功,則返回true
                    return true;
                }
            }
            return false;                                    //所有路徑都無法匹配,返回false
        }
    }
};

/**
 * Your WordDictionary object will be instantiated and called as such:
 * WordDictionary* obj = new WordDictionary();
 * obj->addWord(word);
 * bool param_2 = obj->search(word);
 */