LeetCode 1032. 字符流 (建树的思路——“后缀”树、后缀查询)

字符流
此题主要是建立字典树的思路有点难。
由于每次都要用到字符流的末尾,所以实际上是给定一个长字符串,判断字典树里是否有单词是它的后缀
比如 字典树{"bc","cd"},字符串"abc"的后缀bc字典里出现。
如果是朴素想法的话,那应该每次去切割长的字符串,然后去字典树里查询,这样时间复杂度高达 O ( l e n ( s 1 ) ∗ l e n ( s 2 ) ) O(len(s1)*len(s2)) O(len(s1)len(s2))
但是如果倒过来考虑,就很简单了。
字典树里的单词一开始就反向插入,带查询的字符串也是反向查询,刚好满足题目的要求去,时间复杂度 O ( m i n ( l e n ( s 1 ) , l e n ( s 2 ) ) ) O(min(len(s1),len(s2))) O(min(len(s1),len(s2)))

class StreamChecker {
        struct Node{
        bool isEnd = false;
        Node* children[26] = {0};
    };
    Node* root = new Node;
    void insert(const string& s){
        Node* p = root;
        for(char c:s){
            if(!p->children[c-'a']){
                p->children[c-'a'] = new Node;
            }
            p = p->children[c-'a'];
        }
        p->isEnd = true;
    }
    bool ask(const string& s){
        Node* p = root;
        for(int i=s.size()-1;i>=0;i--){ //反向遍历
            char c = s[i];
            if(!p->children[c-'a']){
                return false;
            }
            p = p->children[c-'a'];
            if(p->isEnd){
                return true;
            }
        }       
        return false;
    }
public:
    string s = ""; 
    StreamChecker(vector<string>& words) {
        for(auto&s:words){
            reverse(s.begin(),s.end());
            insert(s);
        }
    }
    
    bool query(char letter) {
        s.push_back(letter); //如果是头部插入的话,开销很大
        //  s += letter ;  这也是可以的
        return ask(s);
    }
};

/**
 * Your StreamChecker object will be instantiated and called as such:
 * StreamChecker* obj = new StreamChecker(words);
 * bool param_1 = obj->query(letter);
 */

你可能感兴趣的:(LeetCode,#,LC字典树)