211. Add and Search Word Data structure design - cocoder39/coco39_LC GitHub Wiki

211. Add and Search Word - Data structure design

class Trie:
    def __init__(self):
        self.isWord = False
        self.children = collections.defaultdict(Trie)

class WordDictionary:

    def __init__(self):
        self.root = Trie()
        
    def addWord(self, word: str) -> None:
        node = self.root
        for ch in word:
            node = node.children[ch]
        node.isWord = True

    def search(self, word: str) -> bool:
        return self.helper(self.root, word)

    def helper(self, node, word):
        for i, ch in enumerate(word):
            if ch != '.':
                node = node.children.get(ch)
                if node is None:
                    return False
            else:
                for _, child in node.children.items():
                    if self.helper(child, word[i+1:]):
                        return True
                return False
        return node.isWord

===========================================================

class WordDictionary {
public:
    class TriNode {
    public:
        bool isKey;
        vector<TriNode*> children;
        TriNode() : isKey(false), children(vector<TriNode*>(26, nullptr)) {};
    };

    WordDictionary() {
        root = new TriNode();
    }

    // Adds a word into the data structure.
    void addWord(string word) { //O(len)
        TriNode* p = root;
        for (auto c : word) {
            if ((p->children)[c - 'a'] == nullptr)
                (p->children)[c - 'a'] = new TriNode();
            p = (p->children)[c - 'a'];
        }
        p->isKey = 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 search_helper(word, 0, root);
    }
private:
    TriNode* root;
    
    bool search_helper(string& word, int start, TriNode* p) { //worse case O(26^len), eg. '....' matches 'zz..'
        if (start == word.length()) 
            return p->isKey;
        
        if (word[start] != '.') {
            p = (p->children)[word[start] - 'a'];
            return (p && search_helper(word, start + 1, p));
        }
        else {
            for (int i = 0; i < 26; i++) {
                TriNode* node = (p->children)[i];
                if (node && search_helper(word, start + 1, node))
                    return true;
            }
            return false;
        }
    }
};

second implementation: do not forget to initialize root. time complexity is 26^len. to be specific, if there are m '.', then time is O(26^m) because there are 26^m possible words.

class WordDictionary {
public:
    WordDictionary() {
        root = new TrieNode();
    }

    // Adds a word into the data structure.
    void addWord(string word) {
        TrieNode* p = root;
        for (auto c : word) {
            int idx = c - 'a';
            if (! (p->child)[idx])    (p->child)[idx] = new TrieNode();
            p = p->child[idx];
        }
        p->isWord = 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 searchHelper(word, 0, root);
    }
    
    class TrieNode {
    public:
        bool isWord;
        vector<TrieNode*> child;
        TrieNode() {
            isWord = false;
            child = vector<TrieNode*>(26, nullptr);
        }
    };
private:
    TrieNode* root;   
    
    bool searchHelper(string& word, int start, TrieNode* cur) { //cur points to root/word[start-1]
        if (start == word.length()) { //cur points to last char
            return cur->isWord;
        }
        
        for (int i = start; i < word.length(); i++) {
            if (word[i] == '.') {
                for (int j = 0; j < 26; j++) {
                    if (cur->child[j] && searchHelper(word, i + 1, cur->child[j])) {
                        return true;
                    }
                }
                return false;
            } else {
                int idx = word[i] - 'a';
                if (! cur->child[idx])  return false;
                cur = cur->child[idx];
            }
        }
        return cur->isWord;
    }
};

Notes 2020:

  • search1 bfs
  • search2 dfs
class TrieNode:
    def __init__(self):
        self.children = collections.defaultdict(TrieNode)
        self.is_word = False

class WordDictionary:

    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.root = TrieNode()

    def addWord(self, word: str) -> None:
        """
        Adds a word into the data structure.
        """
        cur = self.root
        for ch in word:
            cur = cur.children[ch]
        cur.is_word = True

    def search2(self, word: str) -> bool:
        """
        Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter.
        """
        return self.search_trie(word, self.root)
    
    def search_trie(self, word: str, node: TrieNode):
        for i, ch in enumerate(word):
            if ch is not '.':
                node = node.children.get(ch)
                if node is None:
                    return False
            else:
                for key, val in node.children.items():
                    if self.search_trie(word[i+1:], val):
                        return True
                return False
        return node.is_word
   
    def search1(self, word: str) -> bool:
        """
        Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter.
        """
        queue = collections.deque()
        queue.append(self.root)
        for ch in word:
            if not queue:
                return False
            sz = len(queue)
            for i in range(sz):
                cur = queue.popleft()
                if ch != '.':
                    next_node = cur.children.get(ch)
                    if next_node is not None:
                        queue.append(next_node)
                else:
                    for key, val in cur.children.items():
                        queue.append(val)
        
        while queue:
            cur = queue.pop()
            if cur.is_word:
                return True
        return False
⚠️ **GitHub.com Fallback** ⚠️