LeetCode 1032. 字符流 (建樹的思路——“後綴”樹、後綴查詢)

字符流
此題主要是建立字典樹的思路有點難。
由於每次都要用到字符流的末尾,所以實際上是給定一個長字符串,判斷字典樹裏是否有單詞是它的後綴
比如 字典樹{"bc","cd"},字符串"abc"的後綴bc字典裏出現。
如果是樸素想法的話,那應該每次去切割長的字符串,然後去字典樹裏查詢,這樣時間複雜度高達O(len(s1)len(s2))O(len(s1)*len(s2))
但是如果倒過來考慮,就很簡單了。
字典樹裏的單詞一開始就反向插入,帶查詢的字符串也是反向查詢,剛好滿足題目的要求去,時間複雜度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);
 */
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章