Adding and Searching Words - Data Structure Design [Medium]

1. Title

Please design a data structure that supports adding new words and finding whether a string matches any previously added string.

Implement the dictionary class WordDictionary:
1. ordDictionary()Initialize the dictionary object
2. void addWord(word)Add it wordto the data structure, and then match it
3. bool search(word)If there is a string wordmatching in the data structure, return true; otherwise, return false. wordmay contain some '.', each . can represent any letter.

Example:
input: ["WordDictionary","addWord","addWord","addWord","search","search","search","search"]
[[],["bad"],["dad"],["mad"],["pad"],["bad"],[".ad"],["b.."]]
output:[null,null,null,null,false,true,true,true]

explain:

WordDictionary wordDictionary = new WordDictionary();
wordDictionary.addWord("bad");
wordDictionary.addWord("dad");
wordDictionary.addWord("mad");
wordDictionary.search("pad"); // 返回 False
wordDictionary.search("bad"); // 返回 True
wordDictionary.search(".ad"); // 返回 True
wordDictionary.search("b.."); // 返回 True

1 <= word.length <= 25
addWordThe word in wordconsists of lowercase English letters.
searchThe word in consists of '.' or lowercase English letters.
The maximum 104number of calls addWordis sum.search

2. Code

Dictionary Tree: A dictionary tree (prefix tree) is a tree data structure used to efficiently store and retrieve keys in a string dataset. The prefix tree can use O(∣S∣)the time complexity to complete the following operations, where ∣S|it is inserting a string or querying the length of the prefix:
1. Insert a string into the dictionary tree word;
2. Query wordwhether the string has been inserted into the dictionary tree.

Ideas and algorithms: According to the meaning of the question, WordDictionarythe class needs to support the operations of adding words and searching for words, which can be implemented using a dictionary tree. For adding words, just add the word to the dictionary tree.

For searching words, start searching from the root node of the dictionary tree. Since the words to be searched may contain dots, the processing of dots needs to be considered during the search process. For the case where the current character is a letter or a period, the processing is as follows:
1. If the current character is a letter, determine whether the child node corresponding to the current character exists. If the child node exists, move to the child node and continue. Search for the next character. If the child node does not exist, the word does not exist and return false;
2. If the current character is a dot, since the dot can represent any letter, it is necessary to continue searching for all non-empty child nodes of the current node. Next character.

Repeat the above steps until falsethe last character of the given word is returned or searched. If the last character of a given word is searched, then the given word exists when the last node searched isEndis trueIn particular, when the dot number is searched, as long as there is a non-empty sub-node that can search for the given word, it will be returned true.

class WordDictionary {
    
    
    private Trie root;

    public WordDictionary() {
    
    
        root = new Trie();
    }
    
    public void addWord(String word) {
    
    
        root.insert(word);
    }
    
    public boolean search(String word) {
    
    
        return dfs(word, 0, root);
    }

    private boolean dfs(String word, int index, Trie node) {
    
    
        if (index == word.length()) {
    
    
            return node.isEnd();
        }
        char ch = word.charAt(index);
        if (Character.isLetter(ch)) {
    
    
            int childIndex = ch - 'a';
            Trie child = node.getChildren()[childIndex];
            if (child != null && dfs(word, index + 1, child)) {
    
    
                return true;
            }
        } else {
    
    
            for (int i = 0; i < 26; i++) {
    
    
                Trie child = node.getChildren()[i];
                if (child != null && dfs(word, index + 1, child)) {
    
    
                    return true;
                }
            }
        }
        return false;
    }
}

class Trie {
    
    
    private Trie[] children;
    private boolean isEnd;

    public Trie() {
    
    
        children = new Trie[26];
        isEnd = false;
    }
    
    public void insert(String word) {
    
    
        Trie node = this;
        for (int i = 0; i < word.length(); i++) {
    
    
            char ch = word.charAt(i);
            int index = ch - 'a';
            if (node.children[index] == null) {
    
    
                node.children[index] = new Trie();
            }
            node = node.children[index];
        }
        node.isEnd = true;
    }

    public Trie[] getChildren() {
    
    
        return children;
    }

    public boolean isEnd() {
    
    
        return isEnd;
    }
}

Time complexity: initialized as O(1), adding words is O(∣S∣), searching words is O(∣Σ∣∣S∣), where ∣S∣is the length of the word added or searched each time, Σis the character set, the character set in this question is all lowercase English letters, ∣Σ∣=26. In the worst case, if every character in the word to be searched is a period, then every character has ∣Σ∣a possibility.
Space complexity: O(∣T∣⋅∣Σ∣) , where ∣T∣is the sum of the lengths of all added words, and Σis the character set. The character set in this question is all lowercase English letters, ∣Σ∣=26.

Guess you like

Origin blog.csdn.net/zhengzhaoyang122/article/details/135210840