Implement the StreamChecker class as follows:

StreamChecker(words): Constructor, init the data structure with the given words.
query(letter): returns true if and only if for some k >= 1, the last k characters queried (in order from oldest to newest, including this letter just queried) spell one of the words in the given list.

 
Example:
StreamChecker streamChecker = new StreamChecker(["cd","f","kl"]); // init the dictionary.
streamChecker.query('a');          // return false
streamChecker.query('b');          // return false
streamChecker.query('c');          // return false
streamChecker.query('d');          // return true, because 'cd' is in the wordlist
streamChecker.query('e');          // return false
streamChecker.query('f');          // return true, because 'f' is in the wordlist
streamChecker.query('g');          // return false
streamChecker.query('h');          // return false
streamChecker.query('i');          // return false
streamChecker.query('j');          // return false
streamChecker.query('k');          // return false
streamChecker.query('l');          // return true, because 'kl' is in the wordlist

 
Note:

1 <= words.length <= 2000
1 <= words[i].length <= 2000
Words will only consist of lowercase English letters.
Queries will only consist of lowercase English letters.
The number of queries is at most 40000.

Difficulty: interview

Starter code:

class StreamChecker:
    def __init__(self, words: List[str]):
    def query(self, letter: str) -> bool:
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

Solutions:
class StreamChecker:

    def __init__(self, words: List[str]):
        #reverse trie
        self.trie = {}
        self.stream = deque([])

        for word in set(words):
            node = self.trie       
            for ch in word[::-1]:
                if not ch in node:
                    node[ch] = {}
                node = node[ch]
            node['$'] = word
        
    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        
        node = self.trie
        for ch in self.stream:
            if '$' in node:
                return True
            if not ch in node:
                return False
            node = node[ch]
        return '$' in node


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


\"\"\"
Trie for reversed words
for each letter, we go reversedly of the input stream, and traverse the trie Trie for reversed words
for each letter, we go reversedly of the input stream, and traverse the trie if we can find a word when traversing
\"\"\"
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.stream = deque([])

        for word in set(words):
            node = self.trie       
            for ch in word[::-1]:
                if not ch in node:
                    node[ch] = {}
                node = node[ch]
            node['$'] = word
        
        
    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        
        node = self.trie
        for ch in self.stream:
            if '$' in node:
                return True
            if not ch in node:
                return False
            node = node[ch]
        return '$' in node

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

from collections import deque
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.stream = deque([])

        for word in set(words):
            node = self.trie       
            for ch in word[::-1]:
                if not ch in node:
                    node[ch] = {}
                node = node[ch]
            node['$'] = word
        
        
    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        
        node = self.trie
        for ch in self.stream:
            if '$' in node:
                return True
            if not ch in node:
                return False
            node = node[ch]
        return '$' in node
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.isword = False
        self.children = [None] * 26        

class StreamChecker:

    def __init__(self, words):
        self.root = TrieNode()
        self.lastchars = []
        for word in words:
            self.add(word)
            
        
    def add(self, word):
        parent = self.root
        for c in reversed(word):
            i = ord(c) - 97
            if not parent.children[i]: 
                parent.children[i] = TrieNode()
            parent = parent.children[i]
        parent.isword = True
        
    def search(self, word):
        parent = self.root
        
        for c in reversed(word):
            i = ord(c) - 97
            if parent.isword: return True
            if not parent.children[i]: return False
            parent = parent.children[i]
            
        return parent.isword

    def query(self, letter):
        self.lastchars.append(letter)
        return self.search(self.lastchars)



class StreamChecker:

    def __init__(self, words: List[str]):
        self.words = set(words)
        self.letters = ''
        
    def query(self, letter: str) -> bool:
        self.letters +=letter
        
        for x in self.words:
            if self.letters.endswith(x):
                return True
            
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.waitlist = []
        for word in words:
            t = self.trie
            for w in word:
                if w not in t:
                    t[w] = {}
                t = t[w]
            t['#'] = '#'
        
        self.origin = self.trie.copy()
        self.nodes = []

    def query(self, letter):
        res = False
        self.nodes.append(self.trie)
        new_nodes = []
        for node in self.nodes:
            if letter in node:
                node = node[letter]
                if \"#\" in node:
                    res = True
                new_nodes.append(node)
        self.nodes = new_nodes     
        return res


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        for word in words:
            self.trie.add(word)
        

    def query(self, char: str) -> bool:
        return self.trie.find(char)
    
class Trie:
    class Node:
        def __init__(self, complete=False):
            self.complete = complete
            self.children = {}
        
    def __init__(self):
        self.root = self.Node()
        self.current = []
    
    def add(self, word: str) -> bool:
        node = self.root
        for index, char in enumerate(word):
            if char not in node.children:
                node.children[char] = self.Node(index == len(word) - 1)
            node = node.children[char]
            if index == len(word) - 1:
                node.complete = index == len(word) - 1
        return True
    
    def find(self, char: str) -> bool:
        self.current.append(self.root)
        self.current = [node.children[char] for node in self.current if char in node.children]
        
        return any(node.complete for node in self.current)
        
#         if not self.current or char not in self.current.children:
#             self.current = self.root
#             print(char, 'reset current')
                
#         self.current = self.current.children.get(char)
        
#         if self.current and self.current.complete:
#             return True
#         return False
    
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


# class StreamChecker(object):

#     def __init__(self, words):
#         \"\"\"
#         :type words: List[str]
#         \"\"\"      
#         self.waitlist = []
#         self.trie = dict()
#         for word in words:
#             # create a temporary dict based off our root dict object
#             temp_dict = self.trie
#             for letter in word:
#                 # update our temporary dict and add our current letter and a sub-dictionary
#                 # if key is not in dict, setdefault() will add {key:{}} and return default value {}
#                 # otherwise it will directly return the existing value of key
#                 temp_dict = temp_dict.setdefault(letter, dict())
#             # If our word is finished, add {'#': '#'} at the stopping node
#             temp_dict['#'] = '#'

#     def query(self, letter):
#         \"\"\"
#         :type letter: str
#         :rtype: bool
#         \"\"\"
#         waitlist = []
#         # if letter can be the prefix of word
#         if letter in self.trie:
#             waitlist.append(self.trie[letter])
#         # for each possible prefix, append letter if the new substr still can be a prefix
#         for item in self.waitlist:
#             if letter in item:
#                 waitlist.append(item[letter])
                
#         self.waitlist = waitlist
#         return any('#' in item for item in self.waitlist)
    
class StreamChecker:
    def __init__(self, words: List[str]):
        self.entries = {}
        for word in words:
            curNode = self.entries           
            for i in range(len(word)):
                cur = word[i]
                if cur not in curNode:
                    curNode[cur] = {}
                curNode = curNode[cur]
            curNode[\"#\"] = True
        self.nodes = []


    def query(self, letter: str) -> bool:
        res = False
        self.nodes.append(self.entries)
        new_nodes = []
        for node in self.nodes:
            if letter in node:
                node = node[letter]
                if \"#\" in node:
                    res = True
                new_nodes.append(node)
        self.nodes = new_nodes     
        return res


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


def add(ptr, c, nptrs):
    # scan
    if c in ptr:
        n = ptr[c]
        nptrs.append( n )
        return 'fin' in n
    return False

class StreamChecker:

    def __init__(self, words: List[str]):
        def add(word, i, pos):
            # add to trie
            if i == len(word):
                pos['fin'] = True
                return
            c = word[i]
            if c not in pos:
                pos[c] = { 'with': c }
            add(word, i + 1, pos[c])
            
        self._trie = { 'root': True, 'with': '$' }
        root = self._trie
        for w in words:
            add(w, 0, root)
            
        self._ptrs = []
        self._ptrs.append( root )
        print(\"built\")
        # print(f\"{self._trie}\")

    def query(self, letter: str) -> bool:
        
        found = False
        nptrs = []
        ptrs = self._ptrs
        for p in ptrs:
            if add(p, letter, nptrs):
                found = True
        nptrs.append( self._trie )
        self._ptrs = nptrs
        return found


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker(object):

    def __init__(self, words):  
        self.waitlist = []
        self.trie = dict()
        for word in words:
            temp_dict = self.trie
            for letter in word:
                temp_dict = temp_dict.setdefault(letter, dict())
            temp_dict['#'] = '#'

    def query(self, letter):
        waitlist = []
        if letter in self.trie:
            waitlist.append(self.trie[letter])
        for item in self.waitlist:
            if letter in item:
                waitlist.append(item[letter]) 
        self.waitlist = waitlist
        return any('#' in item for item in self.waitlist)

class StreamChecker:
    def __init__(self, words: List[str]):
        nested = lambda: defaultdict(nested)
        self.root = nested()

        for w in words:
            n = self.root
            for c in w:
                n = n[c]
            n[\"\\0\"] = True
        self.partials = [self.root]

    def query(self, letter: str) -> bool:
        self.partials = [self.root] + [p[letter] for p in self.partials if p[letter]]

        return any(\"\\0\" in p for p in self.partials)


class Trie:

    def __init__(self):
            \"\"\"
            Initialize your data structure here.
            \"\"\"
            self.trie = {}


    def insert(self, word: str) -> None:
        \"\"\"
        Inserts a word into the trie.
        \"\"\"
        trie = self.trie
        for w in word:
            if w not in trie:
                trie[w] = {}
            trie = trie[w]
        trie['#'] = '#'
    
    def search(self, letters):
        
        trie = self.trie
        i = len(letters) - 1
        
        
        for l in letters[::-1]:
            
            if l in trie and '#' in trie[l]:
                print(\"HHHH\")
                return True
                break
            
            if l not in trie:
                return False
            
            trie = trie[l]
            
        if '#' in trie:
            return True
        else:
            return False
            

class StreamChecker:

    def __init__(self, words: List[str]):
        self.letters = []
        
        self.trie_check = Trie()
        for w in words:
            self.trie_check.insert(w[::-1])
        

    def query(self, letter: str) -> bool:
        self.letters.append(letter)
        # # i = len(self.letters) - 1
        
        # node = self.trie_check.trie
        return self.trie_check.search(self.letters)
        
        # while i >= 0:
        #     if '#' in node:
        #         return True
        #     if self.letters[i] not in node:
        #         return False
        #     node = node[self.letters[i]]
        #     i -= 1
        # return True if '#' in node else False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.dict = list(set(words))
        self.queries = \"\"

    def query(self, letter: str) -> bool:
        self.queries += letter
        for w in self.dict:
            l = len(w)
            # print(self.queries[-l:], w)
            if self.queries[-l:] == w:
                return True
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = TrieNode()
        for ele in words:
            self.add(ele)
        self.stack = [self.root]
            
    def add(self,ele):
        current = self.root
        for char in ele:
            current = current.children[char]
        current.last = True
        
    def query(self, letter: str) -> bool:
        flag = False
        new_stack = [self.root]
        for ele in self.stack:
            if letter in ele.children:
                new_stack.append(ele.children[letter])
                if ele.children[letter].last:
                    flag = True
        self.stack = new_stack
        if flag:
            return True
        return False

class TrieNode:
    def __init__(self):
        self.children = collections.defaultdict(TrieNode)
        self.last = False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode():
    def __init__(self):
        self.children = {}
        self.isEnd = False

class Trie():
    def __init__(self):
        self.root = TrieNode()
    
    def insert(self, word):
        node = self.root
        for char in word:
            if char not in node.children:
                node.children[char] = TrieNode()
            node = node.children[char]
        node.isEnd = True

class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.maxlen = len(words)
        self.cache = ''
        for w in words:
            self.trie.insert(w[::-1])
        
    def query(self, letter: str) -> bool:
        self.cache += letter
        self.result = False
        k = 1
        node = self.trie.root
        while k <= len(self.cache):
            char = self.cache[-k]
            if char in node.children:
                self.result = self.result or node.children[char].isEnd
                k += 1
                node = node.children[char]
            else:
                break
        
        if len(self.cache) > self.maxlen:
            self.cache = self.cache[1:]
        return self.result
 

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.is_word = False
        self.chars = {}
        
class Trie:
    def __init__(self):
        self.root = TrieNode()
        self.prev_nodes = []
        
    def addWord(self, word):
        curr = self.root
        for c in word:
            if c not in curr.chars:
                curr.chars[c] = TrieNode()
            curr = curr.chars[c]
        curr.is_word = True

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        
        for word in words:
            self.trie.addWord(word)

    def query(self, letter: str) -> bool:
        curr_nodes = []
        for prev_node in self.trie.prev_nodes:
            if letter in prev_node.chars:
                curr_nodes.append(prev_node.chars[letter])
        if letter in self.trie.root.chars:
            curr_nodes.append(self.trie.root.chars[letter])
        self.trie.prev_nodes = curr_nodes
        found_letter = False
        for node in curr_nodes:
            if node.is_word:
                found_letter = True
        return found_letter


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in words: reduce(dict.__getitem__, w, self.trie)['#'] = True
        self.waiting = []

    def query(self, letter):
        self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any(\"#\" in node for node in self.waiting)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker(object):

    def __init__(self, words):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in words: reduce(dict.__getitem__, w, self.trie)['#'] = True
        self.waiting = []

    def query(self, letter):
        self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any(\"#\" in node for node in self.waiting)


class Trie(object):
    class Node(object):
        def __init__(self, end=False):
            self.children = {}
            self.end = end

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

    def insert(self, word):
        \"\"\"
        Inserts a word into the trie.
        :type word: str
        :rtype: None
        \"\"\"
        current_node = self.root
        prev_node = current_node
        for letter in word:
            if letter not in current_node.children:
                current_node.children[letter] = self.Node()
            prev_node = current_node
            current_node = current_node.children[letter]
        prev_node.children[letter].end = True


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        for w in words:
            self.trie.insert(w)
        self.current_nodes = [self.trie.root]

    def query(self, letter: str) -> bool:
        self.current_nodes = [cn.children[letter] for cn in self.current_nodes if letter in cn.children]
        if self.trie.root not in self.current_nodes:
            self.current_nodes.append(self.trie.root)
        end = any([cn.end for cn in self.current_nodes])
        return end

    

class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = {}
        
        for word in words:
            curnode = self.root
            for ch in word:
                if ch not in curnode:
                    curnode[ch] = {}
                curnode = curnode[ch]
            curnode['is_end'] = True
        
        self.leads = [self.root] # the pointers to the threads we follow right now

    def query(self, letter: str) -> bool:
        next_leads = [self.root]
        found_word = False
        
        for lead in self.leads:
            if letter in lead:
                new_lead = lead[letter]
                next_leads.append(new_lead)
                if 'is_end' in new_lead:
                    found_word = True
            
        self.leads = next_leads
        return found_word


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
    def __init__(self, words: List[str]):
        self.root = {}
        for word in words:
            node = self.root
            for c in word[::-1]:
                if c not in node:
                    node[c] = {}
                node = node[c]
            node['$'] = True
        self.stream = []

    def query(self, letter: str) -> bool:
        self.stream.append(letter)
        node = self.root
        for c in self.stream[::-1]:
            if c in node:
                node = node[c]
                if '$' in node:
                    return True
            else:
                break
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import deque

class StreamChecker:
    TERMINAL = None

    def __init__(self, words: List[str]):
        self.trie = {}
        self.build_trie(words)
        self.cursors = deque([])
        
    def build_trie(self, words: List[str]):
        trie = self.trie
        for word in words:
            node = trie
            for char in word:
                if char not in node:
                    node[char] = {}
                node = node[char]
            node[self.TERMINAL] = True

    def query(self, letter: str) -> bool:
        cursors = self.cursors
        cursors.append(self.trie)
        found = False
        
        valid_cursors = []
        
        while cursors:
            cursor = cursors.popleft()
            if letter in cursor:
                cursor = cursor[letter]
                valid_cursors.append(cursor)
                if self.TERMINAL in cursor:
                    found = True
                    
        cursors.extend(valid_cursors)
                    
        return found


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:

    def __init__(self):
            \"\"\"
            Initialize your data structure here.
            \"\"\"
            self.trie = {}


    def insert(self, word: str) -> None:
        \"\"\"
        Inserts a word into the trie.
        \"\"\"
        trie = self.trie
        for w in word:
            if w not in trie:
                trie[w] = {}
            trie = trie[w]
        trie['#'] = '#'
    
    def search(self, letters):
        
        trie = self.trie
        letters = letters[::-1]
        
        for l in letters:
            
            if '#' in trie:
                return True
            
            if l not in trie:
                return False
            
            trie = trie[l]
            
        if '#' in trie:
            return True
        else:
            return False
            

class StreamChecker:

    def __init__(self, words: List[str]):
        self.letters = []
        
        self.trie_check = Trie()
        for w in words:
            self.trie_check.insert(w[::-1])
        

    def query(self, letter: str) -> bool:
        self.letters.append(letter)
        return self.trie_check.search(self.letters)
        
       


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

from collections import defaultdict


class TrieNode:
    def __init__(self):
        self.children = defaultdict(TrieNode)
        self.end = False

class Trie:
    def __init__(self, words):
        self.root = TrieNode()
        self.processing = []
        for word in words:
            self.add(word)
    
    def add(self, word):
        node = self.root
        for c in word:
            node = node.children[c]
        node.end = True
    
    def search(self, c):
        processed = []
        self.processing.append(self.root)
        found = False
        for node in self.processing:
            if c in node.children:
                node = node.children[c]
                processed.append(node)
                found |= node.end
        
        self.processing = processed
        return found
        
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie(words)

    def query(self, letter: str) -> bool:
        return self.trie.search(letter)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.words={}
        
        for i in words:
            cur=self.words
            for l in i[::-1]:
                if l not in cur:
                    cur[l]={}
                cur=cur[l]
            cur['.']={}
                
        self.his=[]
        
    def query(self, letter: str) -> bool:
        self.his.append(letter)
        cur=self.words
        for i in self.his[::-1]:
            if cur.get(i)==None:
                return False
            cur=cur[i]
            if '.' in cur:
                return True
            
        return False
        

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import deque

class TrieNode:
    def __init__(self, char):
        self.char = char
        self.children = {}
        self.eow = False
        
class Trie:
    def __init__(self):
        self.rootTrie = TrieNode('*')
        self.currNode = self.rootTrie
    
    def addWord(self, word):
        self.currNode = self.rootTrie
        for idx, char in enumerate(word):
            if char not in self.currNode.children:
                charNode = TrieNode(char)
                self.currNode.children[char] = charNode
            
            self.currNode = self.currNode.children[char]

        self.currNode.eow = True
    
    def findNext(self, lettersQ):
        self.currNode = self.rootTrie
        
        for char in lettersQ:
            if char in self.currNode.children:
                self.currNode = self.currNode.children[char]
                
                if self.currNode.eow:
                    return True
            else:
                return False
            
class StreamChecker:

    def __init__(self, words: List[str]):
        self.streamTrie = Trie()
        self.lettersQ = deque()
        
        for word in words:
            self.streamTrie.addWord(word[::-1])

    def query(self, letter: str) -> bool:
        self.lettersQ.appendleft(letter)
        
        if len(self.lettersQ) > 2000:
            self.lettersQ.pop()
            
        return self.streamTrie.findNext(self.lettersQ)

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.is_word = False
        self.children = defaultdict(TrieNode)

class Trie:
    def __init__(self):
        self.root = TrieNode()

    def add_word(self, word):
        node = self.root
        for c in word:
            node = node.children[c]
        node.is_word = True

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        for word in words:
            self.trie.add_word(word)
            
        self.candidates = [self.trie.root]

    def query(self, letter: str) -> bool:
        new_candidates = [self.trie.root]
        ans = False
        for option in self.candidates:
            if letter in option.children:
                child = option.children[letter]
                new_candidates.append(child)
                ans = ans or child.is_word
        self.candidates = new_candidates
        return ans


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    def __init__(self):
        self.children = defaultdict(list)
        self.end_of_word = False

        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = Trie()
        self.nodes = []
        for word in words:
            self.addWord(word)

        
    def addWord(self, word):
        node = self.root
        for w in word:
            if w not in node.children:
                node.children[w] = Trie()
            node = node.children[w]
        node.end_of_word = True

        
    def query(self, letter: str) -> bool:
        self.nodes.append(self.root)
        temp = False
        new_nodes = []
        
        for node in self.nodes:
            if letter in node.children:
                node = node.children[letter]
                if node.end_of_word:
                    temp = True
                new_nodes.append(node)
        self.nodes = new_nodes
        return temp
        
        

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = dict()
        self.wl = []
        for word in words:
            trie = self.trie
            for w in word:
                trie[w] = trie.get(w, dict())
                trie = trie[w]
            trie[\"#\"] = '#'
        
        # print(self.trie)
        

    def query(self, letter: str) -> bool:
        # print(letter, self.wl)
        wl = []
        if letter in self.trie:
            wl.append(self.trie[letter])
        
        for i in self.wl:
            
            if letter in i:
                wl.append(i[letter])
        
        self.wl = wl
        
        return any('#' in i for i in self.wl)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self, value, leaf=False, children=None):
        self.children = children or {}
        self.value = value
        self.leaf = leaf

class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = TrieNode(value=None)
        self.pointers = []
        for word in words:
            node = self.root
            for c in word:
                if c not in node.children:
                    c_node = TrieNode(c)
                    node.children[c] = c_node
                node = node.children[c]
            node.leaf = True
        
    def query(self, letter: str) -> bool:
        result = False
        revised_pointers = []
        self.pointers.append(self.root)
        for pointer in self.pointers:
            if letter in pointer.children:
                node = pointer.children[letter]
                if node.leaf:
                    result |= True
                revised_pointers.append(node)
        self.pointers = revised_pointers
        return result

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = TrieNode()
        self.waiting = []
        for word in words: 
            self.root.insert(word)
        
        
    def query(self, letter: str) -> bool:
        
        temp = []
        for node in self.waiting + [self.root]:
            if letter in node.child:
                temp.append(node.child[letter])
        
        self.waiting = temp
                
                
        for node in self.waiting:
            if node.is_complete:
                return True
        
        return False
            

class TrieNode:
    def __init__(self):
        self.child = {}
        self.is_complete = False
        
    def insert(self,word): 
        node = self
        for letter in word:
            if letter not in node.child:
                new_node = TrieNode()
                node.child[letter] = new_node
            node = node.child[letter]
        node.is_complete = True
        
    
        
        
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        
        
        self.q = []
        
        self.head = {}
        for word in words:
            cur = self.head
            for w in word[::-1]:
                if w not in cur:
                    cur[w] = {}
                
                cur = cur[w]
            
            cur[\"$\"] = True 
        
        

    def query(self, letter: str) -> bool:
        self.q.append(letter)
        
        cur = self.head
        for c in self.q[::-1]:
            if \"$\" in cur:
                return True
            
            if c not in cur:
                return False
            
            cur = cur[c]
            
        
        return '$' in cur


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            root = self.trie
            for ch in word:
                if ch not in root:
                    root[ch]= {}
                root = root[ch]

            root['*'] = True 
        self.storech = []
    def query(self, letter: str) -> bool:
        a = False 
        storech = []
        if letter in self.trie:
            storech.append(self.trie[letter])
        for ele in self.storech:
            if letter in ele:
                storech.append(ele[letter])
        self.storech = storech 
        return any('*' in ele for ele in self.storech)
        
            
            
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.d = defaultdict(dict)
        for word in words:
            word = word[::-1]
            d = self.d
            for c in word[:-1]:
                d[c] = d.get(c) or defaultdict(dict)
                d = d[c]
            c = word[-1]
            if c not in d:
                d[c] = {'0': 1}
            else:
                d[c]['0'] = 1
            self.queue = []


    def query(self, letter: str) -> bool:
        self.queue.append(letter)
        d = self.d
        for c in self.queue[::-1]:
            if c in d:
                d = d[c]
                if '0' in d:
                    return True
            else:
                break
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    _end = '_end_'

    def __init__(self, words):
        self.root = dict()
        self.where = [self.root]
        self.delete = set()
        for word in words:
            current_dict = self.root
            for letter in word:
                current_dict = current_dict.setdefault(letter, {})
            current_dict[Trie._end] = Trie._end

    def next(self, letter):
        ret = False
        self.where.append(self.root)
        for (i, where) in enumerate(self.where):
            if letter not in where:
                self.delete.add(i)
            else:
                self.where[i] = where[letter]
                if Trie._end in where[letter]:
                    ret = True
        for i in reversed(sorted(self.delete)):
            del self.where[i]
        self.delete = set()
        return ret

    def to_delete(self):
        return self.delete

    def has(self, word):
        current_dict = self.root
        for letter in word:
            if letter not in current_dict:
                return False
            current_dict = current_dict[letter]
        return Trie._end in current_dict

    def add(self, word):
        current_dict = self.root
        for letter in word:
            current_dict = current_dict.setdefault(letter, {})
        current_dict[Trie._end] = Trie._end



class StreamChecker:

    def __init__(self, words):
        self.Trie = Trie(words)

    def query(self, letter):
        return(self.Trie.next(letter))



class Node:
    def __init__(self, val, is_word=False):
        self.val = val
        self.children = {}
        self.is_word = is_word

        
    def __repr__(self):
        return self.val


class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = Node(\"\")
        
        for word in words:
            node = self.root
            for letter in word:
                if letter not in node.children:
                    node.children[letter] = Node(letter)
                node = node.children[letter]
            node.is_word = True

        self.nodes = []
            
        
    def query(self, letter: str) -> bool:
        next_nodes = []
        for node in self.nodes:
            if letter in node.children:
                next_nodes.append(node.children[letter])
        self.nodes = next_nodes
        
        if letter in self.root.children:
            self.nodes.append(self.root.children[letter])

        for node in self.nodes:
            if node.is_word:
                return True
            
        return False
        

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    from collections import defaultdict
    
    class TrieNode:
        def __init__(self):
            self.children = defaultdict()
            
    def __init__(self, words: List[str]):
        self.stream = []
        self.root = self.TrieNode()
        curr = self.root
        for word in words:
            for c in reversed(word):
                if c in curr.children.keys():
                    curr = curr.children[c]
                else:
                    curr.children[c] = self.TrieNode()
                    curr = curr.children[c]
            curr.children[\"$\"] = self.TrieNode()
            curr = self.root                

    def query(self, letter: str) -> bool:
        self.stream.append(letter)
        curr = self.root
        for l in reversed(self.stream):
            if l in curr.children.keys():
                curr = curr.children[l]
                if \"$\" in curr.children.keys():
                    return True
            else:
                return False
            
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words):
        \"\"\"
        :type words: List[str]
        \"\"\"      
        self.waitlist = []
        self.trie = dict()
        for word in words:
            temp_dict = self.trie
            for letter in word:
                temp_dict = temp_dict.setdefault(letter, dict())
            temp_dict['#'] = '#'

    def query(self, letter):
        \"\"\"
        :type letter: str
        :rtype: bool
        \"\"\"
        waitlist = []
        if letter in self.trie:
            waitlist.append(self.trie[letter])
        for item in self.waitlist:
            if letter in item:
                waitlist.append(item[letter])
                
        self.waitlist = waitlist
        return any('#' in item for item in self.waitlist)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:
    class TrieNode:
        def __init__(self):
            self.children = {}
            self.terminal = False
            
    def __init__(self, words: List[str]):
        self.array = []
        self.root = self.TrieNode()
        for word in words:
            node = self.root
            for char in word[::-1]:
                if char not in node.children:
                    node.children[char] = self.TrieNode()
                node = node.children[char]
            node.terminal = True

    def query(self, letter: str) -> bool:
        self.array.append(letter)
        node = self.root
        array = self.array[::-1]
        for char in array:
            if char in node.children:
                node = node.children[char]
                if node.terminal:
                    return True
            else:
                return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in words: reduce(dict.__getitem__, w, self.trie)['#'] = True
        self.waiting = []

    def query(self, letter: str) -> bool:
        self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any(\"#\" in node for node in self.waiting)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

from collections import defaultdict
from typing import List, Dict


class TrieNode:
    def __init__(self):
        self.children: Dict[str, TrieNode] = {}
        self.is_terminal: bool = False

    def __repr__(self):
        return f\"<terminal = {self.is_terminal}, children = {self.children}>\"

class StreamChecker:

    def __init__(self, words: List[str]):
        self._starts_with: Dict[str, List[str]] = defaultdict(list)
        unique_words = set(words)
        self._trie = TrieNode()
        for word in unique_words:
            self._add_to_trie(word)
        #print(self._trie)

        self._pointers: List[TrieNode] = []


    def _add_to_trie(self, word: str):
        trie_node = self._trie
        for i, c in enumerate(word):
            if c not in trie_node.children:
                trie_node.children[c] = TrieNode()
            trie_node = trie_node.children[c]
            if i == len(word) - 1:
                trie_node.is_terminal = True


    def query(self, letter: str) -> bool:
        #print(letter)
        #print(f\"Starting out with {self._pointers}\")
        # Advance pointers currently active
        advancing_pointers = []
        found = False

        for trie_node in self._pointers:
            new_node = trie_node.children.get(letter)
            if new_node is not None:
                if new_node.is_terminal:
                    found = True
                advancing_pointers.append(new_node)

        from_root = self._trie.children.get(letter)
        if from_root is not None:
            if from_root.is_terminal:
                found = True
            advancing_pointers.append(from_root)

        self._pointers = advancing_pointers
        return found


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:
    def __init__(self, words: List[str]):
        self.root = {}
        for w in words:
            curr = self.root
            for ch in w:
                if ch not in curr:
                    curr[ch] = {}
                curr = curr[ch]

            curr[0] = None

        self.cursors = []

    def query(self, letter: str) -> bool:
        self.cursors.append(self.root)
        new_cursors = []
        res = False

        for c in self.cursors:
            if letter in c:
                if 0 in c[letter]:
                    res = True
                new_cursors.append(c[letter])

        self.cursors = new_cursors
        return res
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker(object):

    def __init__(self, words):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in words: reduce(dict.__getitem__, w, self.trie)['#'] = True
        self.waiting = []

    def query(self, letter):
        self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any(\"#\" in node for node in self.waiting)
# class Trie:
#     def __init__(self):
#         self.trie = {}
        
#     def add_word(self,word):
#         nextLevel = self.trie
#         for i,char in enumerate(word):
#             isWord = i == len(word) - 1
#             if char in nextLevel:
#                 if isWord:
#                     nextLevel[char].isWord = True
#                 nextLevel = nextLevel[char].children
#             else:
#                 node = TrieNode(char, isWord)
#                 nextLevel[char] = node
#                 nextLevel = nextLevel[char].children
            
        
# class TrieNode:
#     def __init__(self, char, isWord = False):
#         self.char = char
#         self.isWord = isWord
#         self.children = {}


# class StreamChecker:

#     def __init__(self, words: List[str]):
#         self.words = set(words)
#         self.trie = Trie()
#         for word in words:
#             self.trie.add_word(word)
            
#         self.nextLevels = []

#     def query(self, letter: str) -> bool:
#         print(len(self.nextLevels))
#         nextLevels = []
#         isWord = False
#         if len(self.nextLevels):
#             for level in self.nextLevels:
#                 if letter in level:
#                     if level[letter].isWord:
#                         isWord = True
#                     nextLevels.append(level[letter].children)
        
#         if letter in self.trie.trie:
#             nextLevels.append( self.trie.trie[letter].children )
#             if self.trie.trie[letter].isWord:
#                 isWord = True
                
#         self.nextLevels = nextLevels
    
#         return isWord
    



class Tree:
    def __init__(self, val= ''):
        self.val = val
        self.isTerminal = False
        self.subs = dict()
        

class StreamChecker:

    def __init__(self, words: List[str]):
        
        self.possibleNodes = list()
        self.root = Tree()
        
        for word in words:
            traverser = self.root
            for char in word:
                if char in traverser.subs:
                    traverser=traverser.subs[char]
                else:
                    node = Tree(char)
                    traverser.subs[char] = node
                    traverser = node
            traverser.isTerminal = True
        

    def query(self, letter: str) -> bool:
        
        newPossibleNodes = []
        if letter in self.root.subs:
            newPossibleNodes.append(self.root.subs[letter])
            
        
        for node in self.possibleNodes:
            if letter in node.subs:
                newPossibleNodes.append(node.subs[letter])
                
        
        self.possibleNodes = newPossibleNodes
        
        for node in newPossibleNodes:
            if node.isTerminal:
                return True
            
        return False
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class WordNode:
    def __init__(self):
        self.children = [None] * 26
        self.isFront = False

class WordTrie:
    def __init__(self):
        self.head = WordNode()
        
    def addWord(self, word):
        node = self.head
        for c in word[::-1]:
            if not node.children[ord(c)-ord('a')]:
                node.children[ord(c)-ord('a')] = WordNode()
            node = node.children[ord(c)-ord('a')]
        node.isFront = True
        
    
class StreamChecker:

    def __init__(self, words: List[str]):
        self.Trie = WordTrie()
        for w in words:
            self.Trie.addWord(w)
        self.queries = []

    def query(self, letter: str) -> bool:
        self.queries.append(letter)
        node = self.Trie.head
        for l in self.queries[::-1]:
            if not node.children[ord(l)-ord('a')]: return False
            node = node.children[ord(l)-ord('a')]
            if node.isFront: return True
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class trie:
    def __init__(self,val=None):
        self.val = val
        self.next = {}
        self.is_complete = False
    
class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = trie()
        ### insert all words in trie
        for w in words:
            node=self.root
            for c in w[::-1]:
                if c not in node.__next__:
                    node.next[c] = trie(c)
                node=node.next[c]
            node.is_complete=True
        
        ###to keep track of previous queries
        self.queries = []
        
        
        
    def query(self, letter: str) -> bool:
        self.queries.append(letter)
        
        ### search in trie
        node = self.root
        for c in self.queries[::-1]:
            if c not in node.__next__:
                return False
            node=node.next[c]
            if node.is_complete:
                return True
            
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    \"\"\"
    Keeps the list of Node, as entry point, using hashing.
    \"\"\"
    nodes = {}
    
class Node:
    char_id = None
    end = False
    next_char_ids = []
    
class StreamChecker:
    def __init__(self, words: List[str]):
        # self.char_set = set()
        # for word in words:
        #     self.char_set = self.char_set.union(iter(word))
        self.trie = self.build_trie(words)
        self.curr_tries = []
        
    def build_trie(self, words):
        \"\"\"
        Building reverse trie can be usable for 
        suffix search.
        \"\"\"
        trie = {}
        for word in words:
            c = word[0]
            if c in trie:
                trie_tmp = trie[c]
            else:
                trie[c] = {}
                trie_tmp = trie[c]

            for c in word[1:]:
                if c not in trie_tmp:
                    trie_tmp[c] = {}
                trie_tmp = trie_tmp[c]
            trie_tmp[\"ends\"] = True
        return trie        
    
    def query(self, char) -> bool:
        \"\"\"
        Keep the Trie Tree traversal pointer.
        \"\"\"
        if char in self.trie:
            self.curr_tries.append(self.trie)
        
        new_curr_tries = []
        a_word = False
        for ind, curr_trie in enumerate(self.curr_tries):
            if char in curr_trie:
                curr_trie[char] and new_curr_tries.append(curr_trie[char])
                # Once it turns positive, stay positive. Means one of the
                # trie path, we found word boundary.
                a_word = a_word or \"ends\" in curr_trie[char]
        self.curr_tries = new_curr_tries
        return a_word
        
    def query1(self, char: str) -> bool:
        if self.curr_trie:
            if char in self.curr_trie:
                a_word = \"ends\" in self.curr_trie[char]
                self.curr_trie = self.curr_trie[char]
                return a_word
            else:
                self.curr_trie = {}
                return False
        else:
            # Address the chance of single char only words.
            self.curr_trie = self.trie.get(char, {})
            return \"ends\" in self.curr_trie
        
        
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self):
        self.isword = False
        self.children = [None] * 26        

class StreamChecker:

    def __init__(self, words):
        self.root = TrieNode()
        self.lastchars = ''
        self.maxlen = 0
        for word in words:
            self.add(word)
            self.maxlen = max(self.maxlen, len(word))
            
        
    def add(self, word):
        parent = self.root
        for c in reversed(word):
            i = ord(c) - 97
            if not parent.children[i]: 
                parent.children[i] = TrieNode()
            parent = parent.children[i]
        parent.isword = True
        
    def search(self, word):
        parent = self.root
        
        for c in word:
            i = ord(c) - 97
            if parent.isword: return True
            if not parent.children[i]: return False
            parent = parent.children[i]
            
        return parent.isword

    def query(self, letter):
        self.lastchars = (letter + self.lastchars)[0 : self.maxlen]
        return self.search(self.lastchars)



class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.possible = []
        for word in words:
            t = self.trie
            for c in word:
                if c not in t:
                    t[c] = {}
                t = t[c]
            t['#'] = '#'

    def query(self, letter: str) -> bool:
        temp = []
        if letter in self.trie:
            temp.append(self.trie[letter])
        for d in self.possible:
            if letter in d:
                temp.append(d[letter])
        self.possible = temp
        return any('#' in item for item in self.possible)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words :
            cur = self.trie
            for chrs in word:
                if chrs not in cur:
                    cur[chrs] = {}
                cur = cur[chrs]
            cur['#'] = True
        self.stream = collections.deque()
        print((self.trie))

    def query(self, letter: str) -> bool:
        temp = collections.deque()
        self.stream.append(self.trie)
        for p in self.stream:
            if letter in p:
                temp.append(p[letter])
        self.stream = temp
        for p in self.stream:
            if '#' in p:
                return True
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.tree = Tree('0', [])
        for item in words:
            curr = self.tree
            for letter in item[::-1]:
                result = curr.in_list(letter)
                if result is None:
                    curr.subtrees.append(Tree(letter, []))
                    curr = curr.subtrees[-1]
                else:
                    curr = curr.subtrees[result]
            curr.food = True
        self.q = ''

    def query(self, letter: str) -> bool:
        self.q += letter
        reverse_q = self.q[::-1]
        curr = self.tree
        for letter in reverse_q:
            result = curr.in_list(letter)
            if result is None:
                return False
            else:
                curr = curr.subtrees[result]
                if curr.food:
                    return True
        return False


class Tree:
    def __init__(self, root, subtrees: List):
        self.root = root
        self.food = False
        self.subtrees = subtrees

    def in_list(self, letter: str):
        for i, item in enumerate(self.subtrees):
            if item.root == letter:
                return i
        return None

class TrieNode:
    def __init__(self):
        self.letters = {}
        self.word = False        
    def trie(self, words):
        root = TrieNode()
        for word in words:
            current = root
            for letter in word:
                if letter not in current.letters:
                    current.letters[letter] = TrieNode()
                current = current.letters[letter]
            current.word = True
        return root
            

class StreamChecker:

    def __init__(self, words: List[str]):
        trie = TrieNode()
        self.root = trie.trie(words)
        self.left = [self.root]
        
                

    def query(self, letter: str) -> bool:
        right = [self.root]
        finded = False
        for trie in self.left:
            if letter in trie.letters:
                tmp = trie.letters[letter]
                right += [tmp]
                if tmp.word:
                    finded = True
        self.left = right
        return finded
                    
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:    
    def __init__(self, words: List[str]):
        self.data = {}
        for word in words:
            self._add_word(word)
        self.q = []
    
    def _add_word(self, word):
        word += '$'
        d = self.data
        for char in word:
            if char not in d:
                d[char] = {}
            d = d[char]

    def query(self, letter: str) -> bool:
        new_q = []
        
        if letter in self.data:
            new_q.append(self.data[letter])
        
        for acc in self.q:
            if letter in acc:
                new_q.append(
                    acc[letter]
                )
        self.q = new_q
        
        for acc in self.q:
            if '$' in acc:
                return True
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie = {}
        self.nodes = []
        for word in words:
            node = self.trie
            for char in word:
                if char not in node:
                    node[char] = {}
                node = node[char]
            node['end'] = True

    def query(self, letter: str) -> bool:
        self.nodes.append(self.trie)
        temp = False
        new_nodes = []
        for node in self.nodes:
            if letter in node:
                node = node[letter]
                if 'end' in node:
                    temp = True
                new_nodes.append(node)
        self.nodes = new_nodes
        return temp


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for w in words:
            node = self.trie
            for char in w:
                node.setdefault(char,{})
                node = node[char]
            node.setdefault('*',w)
        self.curr = deque([self.trie])

    def query(self, letter: str) -> bool:
        ret = False
        for _ in range(len(self.curr)):
            node = self.curr.popleft()
            if letter in node:
                node = node[letter]
                self.curr.append(node)
                if '*' in node:
                    ret = True
        self.curr.append(self.trie)
        return ret


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


def to_index(c):
    return ord(c) - ord('a')

class Node:
    def __init__(self, val = None):
        self.val = val
        self.end = False
        self.childs = [None] * (ord('z') - ord('a') + 1)

class Trie:

    def __init__(self):
        self.root = Node()
        

    def insert(self, word: str) -> None:
        ptr = self.root
        for c in word:
            i = to_index(c)
            if ptr.childs[i] is None:
                node = Node(c)
                ptr.childs[i] = node
            ptr = ptr.childs[i]
        ptr.end = True

    def search(self, word: str) -> bool:
        ptr = self.root
        for c in word:
            i = to_index(c)
            if ptr.childs[i] is None:
                return False
            ptr = ptr.childs[i]
        return ptr.end == True
        

    def startsWith(self, prefix: str) -> bool:
        ptr = self.root
        for c in prefix:
            i = to_index(c)
            if ptr.childs[i] is None:
                return False
            ptr = ptr.childs[i]
        return True     

class StreamChecker:

    def __init__(self, words: List[str]):
        self.t = Trie()
        for w in words:
            self.t.insert(w)
        self.d = set()
        self.n = 2000
        self.k = deque()
        self.store = {}

    def query(self, letter: str) -> bool:
        r = False
        if len(self.k) == self.n:
            self.k.popleft()
        i = to_index(letter)
        self.k.append(i)
        v = self.store.get(tuple(self.k), None)
        if v is not None:
            self.d, r = v
            return r
        new_d = set()
        for node in self.d:
            if node.childs[i] is not None:
                new_d.add(node.childs[i])
                if node.childs[i].end: r = True
        if self.t.root.childs[i] is not None:
            new_d.add(self.t.root.childs[i])
            if self.t.root.childs[i].end: r = True
        self.d = tuple(new_d)
        self.store[tuple(self.k)] = (self.d, r)
        return r


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Node:
    def __init__(self):
        self.c = collections.defaultdict(Node)
        self.e = 0
    
class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = Node()
        for w in words:
            temp = self.root
            for i in w:
                temp = temp.c[i]
            temp.e = 1
        self.w = []

    def query(self, letter: str) -> bool:
        # isIn = 0
        # temp = []
        self.w = [i.c[letter] for i in self.w+[self.root] if letter in i.c]
        return any(i.e for i in self.w)
#                     if letter in i.c:
#                         temp.append(i.c[letter])
#                         if not isIn:
#                             isIn = temp[-1].e
                
#         if letter in self.root.c:
#             temp.append(self.root.c[letter])
#             if not isIn:
#                 isIn = temp[-1].e
                
        # self.w = temp.copy()
        # print(i.c. for i in self.w)
        # return isIn
                
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import deque
class Node:
    def __init__(self, char):
        self.char = char
        self.children = {}
        self.word = False

class Trie:
    def __init__(self):
        self.root = Node(\"\")

    def add_word(self, word):
        node = self.root
        for char in word:
            if char not in node.children:
                node.children[char] = Node(char)
            node = node.children[char]
        node.word = True

    def prefix_of_word_exists(self, word):
        node = self.root
        for char in word:
            if char not in node.children:
                return False
            node = node.children[char]
            if node.word:
                return True
        return False
        

class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.max_word_length = 0
        for word in words:
            self.trie.add_word(word[::-1])
            self.max_word_length = max(self.max_word_length, len(word))
        self.q = deque()

    def query(self, letter: str) -> bool:
        if len(self.q) == self.max_word_length:
            self.q.pop()
        self.q.appendleft(letter)
        return self.trie.prefix_of_word_exists(self.q)
    # [\"cde\"]
    # [\"c\" Node<d>, \"d\" None] e
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self):
        self.child = defaultdict(TrieNode)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = TrieNode()
        self.waitlist = []
        for word in words:
            node = self.root
            for ch in word:
                node = node.child[ch]
            
            node.child['#'] = defaultdict(TrieNode)

    def query(self, letter: str) -> bool:
        waitlist = []
        now = self.root
        if letter in now.child:
            waitlist.append(now.child[letter])

        for node in self.waitlist:
            if letter in node.child:
                waitlist.append(node.child[letter])
                
        self.waitlist = waitlist
        for node in waitlist:
            if '#' in node.child:
                return True
            
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.points = [self.trie]
        for word in words:
            cur = self.trie
            for w in word:
                if not w in cur:
                    cur[w] = {}
                cur = cur[w]
            cur['#'] = None

    def query(self, letter: str) -> bool:
        temp = [self.trie]
        ret = False
        for p in self.points:
            if letter in p:
                p = p[letter]
                if '#' in p:
                    ret = True
                temp.append(p)
        self.points = temp
        return ret


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            temp = self.trie
            for char in word:
                if char not in temp:
                    temp[char] = {}
                temp = temp[char]
            temp['*'] = True
        self.pointer = deque()

    def query(self, letter: str) -> bool:
        temp = self.trie
        self.pointer.append(temp)
        length = len(self.pointer)
        flag = False
        for i in range(length):
            node = self.pointer.popleft()
            if letter in node:
                node = node[letter]
                self.pointer.append(node)
                if '*' in node:
                    flag = True
        return flag
        
                


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.d = {}
        for w in words:
            tmp = self.d
            for i in w:
                tmp = tmp.setdefault(i, {})
            tmp['#'] = {}
        self.cur = []
    # def merge(self, d1, d2):
    #     res = {}
    #     for k in set(list(d1.keys()) + list(d2.keys())):
    #         if k in d1 and k in d2:
    #             res[k] = self.merge(d1[k], d2[k])
    #         elif k in d1:
    #             res[k] = d1[k]
    #         else:
    #             res[k] = d2[k]
    #     return res

    def query(self, letter: str) -> bool:
        flag = False
        cur_new = []
        for prefix in self.cur:
            if letter in prefix:
                cur_new.append(prefix[letter])
                if \"#\" in prefix[letter]:
                    flag = True
        if letter in self.d:
            cur_new.append(self.d[letter])
            if \"#\" in self.d[letter]:
                flag = True
        self.cur = cur_new
        return flag

        # flag = False
        # tmp = {}
        # if letter in self.cur:
        #     tmp = self.cur[letter]
        #     if ('#' in tmp):
        #         flag = True
        #         tmp.pop('#')
        # self.cur = self.merge(tmp, self.d)
        # return flag
         
            
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self):
        self.neighbors = defaultdict(TrieNode)
        self.isWord = False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = TrieNode()
        for word in words:
            node = self.root
            for c in word:
                node = node.neighbors[c]
            node.isWord = True
        self.nodes = []

    def query(self, letter: str) -> bool:
        isWord = False
        newNodes = []
        self.nodes.append(self.root)
        for node in self.nodes:
            if letter in node.neighbors:
                temp = node.neighbors[letter]
                isWord |= temp.isWord
                newNodes.append(temp)
        self.nodes = newNodes
        return isWord

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for w in words:
            node = self.trie
            for i in w:
                if i not in node:
                    node[i] = {}
                node = node[i]
            node[\"end\"] = True
        self.active = {\"\" : self.trie}

    def query(self, letter: str) -> bool:
        new_active = {}
        ret = False
        count = 0
        
        for a in self.active:
            node = self.active[a]
            if letter in node:
                node = node[letter]
                if \"end\" in node:
                    ret = True
                new_active[count] = node
                count += 1
        new_active[count] = self.trie
        self.active = new_active
        return ret

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker(object):

    def __init__(self, words):
        \"\"\"
        :type words: List[str]
        \"\"\"      
        self.waitlist = []
        self.trie = dict()
        for word in words:
            # create a temporary dict based off our root dict object
            temp_dict = self.trie
            for letter in word:
                # update our temporary dict and add our current letter and a sub-dictionary
                # if key is not in dict, setdefault() will add {key:{}} and return default value {}
                # otherwise it will directly return the existing value of key
                temp_dict = temp_dict.setdefault(letter, dict())
            # If our word is finished, add {'#': '#'} at the stopping node
            temp_dict['#'] = '#'

    def query(self, letter):
        \"\"\"
        :type letter: str
        :rtype: bool
        \"\"\"
        waitlist = []
        # if letter can be the prefix of word
        if letter in self.trie:
            waitlist.append(self.trie[letter])
        # for each possible prefix, append letter if the new substr still can be a prefix
        for item in self.waitlist:
            if letter in item:
                waitlist.append(item[letter])
                
        self.waitlist = waitlist
        return any('#' in item for item in self.waitlist)

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.word_buf = []
        self.wordDict = {}
        for w in words:
            temp_dict = self.wordDict
            for c in w:
                temp_dict = temp_dict.setdefault(c, dict())
            temp_dict[\"EOS\"] = \"EOS\"
        
    def query(self, letter: str) -> bool:
        waitlist = []
        # if letter can be the prefix of word
        if letter in self.wordDict:
            waitlist.append(self.wordDict[letter])
        # for each possible prefix, append letter if the new substr still can be a prefix
        for item in self.word_buf:
            if letter in item:
                waitlist.append(item[letter])
                
        self.word_buf = waitlist
        return any('EOS' in item for item in self.word_buf)
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TRIE:
    
    def __init__(self,next_letters=None,flag=False):
        if not next_letters:
            self.next_letters = {}
        else:
            self.next_letters = next_letters
        self.flag = flag
        
        
class StreamChecker:

    def __init__(self, words: List[str]):
        # build a trie
        self.root = TRIE()
        for word in words:
            curr_node = self.root
            for l in word:
                if l not in curr_node.next_letters:
                    new_node = TRIE()
                    curr_node.next_letters[l] = new_node
                    curr_node = new_node
                else:
                    curr_node = curr_node.next_letters[l]
            curr_node.flag = True
        # a collection of curr_nodes
        self.curr_nodes = set([self.root])
        
    def query(self, letter: str) -> bool:
        found = False
        new_curr_nodes = set([self.root]) # always add back root
        for node in self.curr_nodes: 
            if letter in node.next_letters:
                curr_node = node.next_letters[letter]
                new_curr_nodes.add(curr_node)
                if curr_node.flag:
                    found = True
        self.curr_nodes = new_curr_nodes
        return found
                
                
                
            
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    
    def __init__(self):
        self.children = {}
        self.is_end = False

class Trie:
    
    def __init__(self):
        self.root = TrieNode()
    
    def addWord(self, word):
        curr = self.root
        for ch in word:
            if ch not in curr.children:
                new_node = TrieNode()
                curr.children[ch] = new_node
            curr = curr.children[ch]
        curr.is_end = True
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        for word in words:
            self.trie.addWord(reversed(word))
        self.queue = collections.deque()
            
    def query(self, letter: str) -> bool:
        self.queue.appendleft(letter)
        curr = self.trie.root
        for ch in self.queue:
            if ch not in curr.children:
                return False
            if ch in curr.children:
                curr = curr.children[ch]
                if curr.is_end:
                    return True



# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    \"\"\"
    Implementation of a prefix tree.
    \"\"\"

    def __init__(self):
        self.root = {}

    def add_word(self, w: str) -> None:
        currNode = self.root
        for c in w:
            if c not in currNode:
                currNode[c] = {}

            currNode = currNode[c]

        currNode['#'] = True  # Mark the word end.


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        for w in words:
            self.trie.add_word(w)

        self.startNodes = []

    def query(self, letter: str) -> bool:
        nextStartNodes = [
            node[letter] for node in self.startNodes + [self.trie.root]
            if letter in node]
        self.startNodes = nextStartNodes
        return any('#' in node for node in nextStartNodes)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.words = set(words)
        self.words_trie = defaultdict(dict)
        
        for word in words:
            trie_node = self.words_trie[word[-1]]
            for letter in word[-2::-1]:
                next_node = trie_node.setdefault(letter, {})
                trie_node = next_node
            trie_node[None] = None
        
        print((self.words_trie))
        self.queries = []

    def query(self, letter: str) -> bool:
        self.queries.append(letter)
        
        trie_node = None
        for query_letter in self.queries[::-1]:
            if trie_node is None:
                trie_node = self.words_trie.get(query_letter, {})
            else:
                trie_node = trie_node.get(query_letter, {})
            
            if not trie_node:
                break
            elif None in trie_node:
                return True
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        for word in words:
            self.trie.add(word)
        self.consideration = []

    def query(self, letter: str) -> bool:
        self.consideration = [node.words[letter] for node in self.consideration + [self.trie] if letter in node.words]
        return any(node.is_word for node in self.consideration)
        
            

class Trie:
    def __init__(self):
        self.is_word = False
        self.prefix = ''
        self.words = {}
    
    def add(self, word):
        if not word:
            self.is_word = True
            return
        if word[0] in self.words:
            self.words[word[0]].add(word[1:])
        else:
            n = Trie()
            n.prefix = self.prefix + word[0]
            self.words[word[0]] = n
            self.words[word[0]].add(word[1:])



# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
    
            

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            startTrie = self.trie
            for c in word:
                if c not in startTrie:
                    startTrie[c] = {}
                startTrie = startTrie[c]
            startTrie[\"isEnd\"] = True
        self.openTries = []
        # print(self.trie)

    def query(self, letter: str) -> bool:
        
        # print(self.openTries)
        
        #Insert this new letter into our tries.
        if letter in self.trie:
            self.openTries.append(self.trie)
        
        #Increment these tries that are still open.
        found = False
        tempTries = []
        while self.openTries:
            trie = self.openTries.pop()
            if letter in trie:
                trie = trie[letter]
                if \"isEnd\" in trie:
                    found = True
                tempTries.append(trie)
        self.openTries = tempTries
        return found


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            self.add_word_to_trie(self.trie, word, 0)
        self.pointers = {}
        self.q_no = 0
        
    def query(self, letter: str) -> bool:
        self.q_no += 1
        self.pointers[self.q_no] = self.trie
        result = False
        to_delete = []
        for q_no, pointer in list(self.pointers.items()):
            if letter not in pointer:
                to_delete.append(q_no)
                continue
            self.pointers[q_no] = pointer[letter]
            result = result or 1 in self.pointers[q_no]
        for del_c in to_delete:
            del self.pointers[del_c]
        return result
    
    def add_word_to_trie(self, node, word, i):
        if i == len(word):
            node[1] = True
            return
        if word[i] not in node:
            node[word[i]] = {}
        self.add_word_to_trie(node[word[i]], word, i+1)
        

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            d = self.trie
            for c in word:
                if c not in d:
                    d[c] = {}
                d = d[c]
            d['*'] = True
        self.open_words = []

    def query(self, letter: str) -> bool:
        found = False
        new_open_words = []
        if letter in self.trie:
            new_open_words.append(self.trie[letter])
            if '*' in self.trie[letter]:
                found = True
        for word in self.open_words:
            if letter in word:
                if '*' in word[letter]:
                    found = True
                new_open_words.append(word[letter])
        self.open_words = new_open_words
        return found

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.char_stream = []
        for word in words:
            self.trie.insert(word[::-1])

    def query(self, letter: str) -> bool:
        self.char_stream.append(letter)
        return self.trie.checkStream(self.char_stream[::-1])


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self, children, isEnd=False):
        self.children = children
        self.isEnd = isEnd

class Trie:

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

    def insert(self, word: str) -> None:
        \"\"\"
        Inserts a word into the trie.
        \"\"\"
        node = self.root
        for i, c in enumerate(word):
            if c in node.children:
                node = node.children[c]
            else:
                node.children[c] = TrieNode({})
                node = node.children[c]
                
        node.isEnd = True

    def search(self, word: str) -> bool:
        \"\"\"
        Returns if the word is in the trie.
        \"\"\"
        node = self.root
        for c in word:
            if c in node.children:
                node = node.children[c]
            else:
                return False
            
        return node.isEnd
    
    
    def checkStream(self, char_stream: List[str]) -> bool:
        node = self.root
        for c in char_stream:
            if c in node.children:
                node = node.children[c]
                if node.isEnd:
                    return True
            else:
                return False
            
        return False
            

    def startsWith(self, prefix: str) -> bool:
        \"\"\"
        Returns if there is any word in the trie that starts with the given prefix.
        \"\"\"
        node = self.root
        for c in prefix:
            if c in node.children:
                node = node.children[c]
            else:
                return False
        return True


# Your Trie object will be instantiated and called as such:
# obj = Trie()
# obj.insert(word)
# param_2 = obj.search(word)
# param_3 = obj.startsWith(prefix)

class TrieNode:
    def __init__(self):
        self.word = False
        self.children = {}

class Trie:
    def __init__(self):
        self.head = TrieNode()
        self.head.word = True
        
    def insert(self, word):
        itr = self.head
        for c in word:
            if c not in itr.children:
                itr.children[c] = TrieNode()
            itr = itr.children[c]
        itr.word = True
        
    def contains(self, word):        
        itr = self.head
        for c in word:
            if c in itr.children:
                itr = itr.children[c]
                if itr.word: return True
            else:
                return False
        return itr.word        
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        for word in words:
            self.trie.insert(word[::-1])
        self.word = []
    def query(self, letter: str) -> bool:
        
        self.word.append(letter)
        return self.trie.contains(self.word[::-1])

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        
        self.dic = {}
        
        for w in words:
            dic = self.dic
            for c in w[::-1]:
                if not c in dic:
                    dic[c] = {}
                dic = dic[c]
            dic['#'] = True
            
        self.stack = []

    def query(self, letter: str) -> bool:
        
        self.stack.append(letter)
        
        dic = self.dic
        
        for c in self.stack[::-1]:
            if '#' in dic:
                return True
            
            if c not in dic:
                return False
            
            dic = dic[c]
        
        return dic.get('#', False)

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            node = self.trie
            for c in word:
                try:
                    node = node[c]
                except KeyError:
                    n = node[c] = {}
                    node = n
            node['$'] = None
        self.index = 0
        self.nodes = {}

    def query(self, letter: str) -> bool:
        nodes = {}
        self.nodes[self.index] = self.trie
        for i, node in list(self.nodes.items()):
            try:
                nodes[i] = node[letter]
            except KeyError:
                pass
        
        self.nodes = nodes
        self.index += 1
        return any('$' in node for node in list(nodes.values()))
                


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.entries = {}
        for word in words:
            curNode = self.entries
            for i in range(len(word)):
                cur = word[i]
                if cur not in curNode:
                    curNode[cur] = {}
                curNode = curNode[cur]
            curNode[\"#\"] = True
        self.nodes = []
        

    def query(self, letter: str) -> bool:
        res = False
        self.nodes.append(self.entries)
        new_nodes = []
        for node in self.nodes:
            if letter in node:
                node = node[letter]
                if \"#\" in node:
                    res = True
                new_nodes.append(node)
        self.nodes = new_nodes     
        return res


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

from typing import List

root = '@'
marker = '$'


class TrieNode:
    def __init__(self, letter):
        self.letter = letter
        self.children = dict()


class StreamChecker:

    def __init__(self, words: List[str]):
        self.spelt = False
        self.root = TrieNode(root)
        self.pointers = [self.root]

        for word in words:
            self.trie_insert(word)

    def trie_insert(self, word: str):
        current = self.root

        for letter in word:
            if letter in current.children:
                current = current.children[letter]
            else:
                letter_node = TrieNode(letter)
                current.children[letter] = letter_node
                current = letter_node
        current.children[marker] = TrieNode(marker)

    def query(self, letter: str) -> bool:
        new_ptrs = []
        self.spelt = False
        for ptr in self.pointers:
            if letter in ptr.children:
                advanced_ptr = ptr.children[letter]
                if marker in advanced_ptr.children:
                    self.spelt = True
                new_ptrs.append(advanced_ptr)
                
        self.pointers = new_ptrs + [self.root]
        return self.spelt



class StreamChecker(object):
    def __init__(self, words):
        self.words = set(words)
        self.added_chars = \"\"

    def query(self, char):
        self.added_chars += char
        for w in self.words:
            if self.added_chars.endswith(w):
                return True
        else:
            return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Node:
    def __init__(self, x):
        self.val=x
        self.next={}
        self.word=False
class Trie:
    def __init__(self):
        self.root=Node(None)
    
    def add(self, word):
        root=self.root
        for w in word:
            if w not in root.__next__:
                node=Node(w)
                root.next[w]=node
            root=root.next[w]
        root.word=True
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie=Trie()
        self.key={}
        self.pre=set([])
        for i in words:
            self.trie.add(i)

    def query(self, letter: str) -> bool:
        root=self.trie.root
        temp=set([])
        ans=False
        for i in self.pre:
            if letter in i.__next__:
                node=i.next[letter]
                if node.word:
                    ans=True
                temp.add(node)
        if letter in root.__next__:
            node=root.next[letter]
            temp.add(node)
            if node.word:
                ans=True
        self.pre=temp
        return ans

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self, val: str, children: dict, isEnd=False):
        self.val = val
        self.children = children
        self.isEnd = isEnd
        
        
class Trie:

    def __init__(self):
        \"\"\"
        Initialize your data structure here.
        \"\"\"
        self.root = TrieNode(None, {}, False)

    def insert(self, word: str) -> None:
        \"\"\"
        Inserts a word into the trie.
        \"\"\"
        node = self.root
        for i, l in enumerate(word):
            if l in node.children:
                node = node.children[l]
            else:
                node.children[l] = TrieNode(l, {}, i == len(word) - 1)
                node = node.children[l]
                
        node.isEnd = True

    def search(self, word: str) -> bool:
        \"\"\"
        Returns if the word is in the trie.
        \"\"\"
        node = self.root
        for l in word:
            if l in node.children:
                node = node.children[l]    
            else:
                return False
        return node.isEnd

    def startsWith(self, prefix: str) -> bool:
        \"\"\"
        Returns if there is any word in the trie that starts with the given prefix.
        \"\"\"
        node = self.root
        for l in prefix:
            if l in node.children:
                node = node.children[l]
            else:
                return False
        return True
    
    def search_for_multiple(self, letters):
        node = self.root
        
        for l in letters[::-1]:
            if l in node.children:
                node = node.children[l]
            else:
                return False
            
            if node.isEnd:
                return True

class StreamChecker:

    def __init__(self, words: List[str]):
        self.my_trie = Trie()
        
        self.letters = []
        
        for word in words:
            self.my_trie.insert(word[::-1])

    def query(self, letter: str) -> bool:
        self.letters.append(letter)
        
        return self.my_trie.search_for_multiple(self.letters)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Node():
    def __init__(self, val):
        self.val = val
        self.children = {}
        self.end = False


class WordTree:
    def __init__(self):
        self.root = Node(0)

    def add_word(self, word):
        cur = self.root
        for c in word[::-1]:
            if c in cur.children:
                cur = cur.children[c]
            else:
                cur.children[c] = Node(c)
                cur = cur.children[c]
        cur.end = True


class StreamChecker:

    def __init__(self, words):
        self.tree = WordTree()
        for word in words:
            self.tree.add_word(word)
        self.query_l = []

    def query(self, letter: str) -> bool:
        self.query_l.append(letter)
        cur = self.tree.root
        for c in self.query_l[::-1]:
            if c not in cur.children:
                return False
            cur = cur.children[c]
            if cur.end:
                return True
        return False


# class StreamChecker:
#     def __init__(self, words: List[str]):
#         self.root = {}
#         self.max_len = 0
#         self.buff = []
#         for word in words:
#             self.max_len = max(self.max_len , len(word))
#             cur = self.root
            
#             for w in word[::-1]:
#                 cur = cur.setdefault(w, {})
#             cur['*'] = '*'
        
        

#     def query(self, letter: str) -> bool:
#         self.buff = [letter] + self.buff 
#         # if len(self.buff) > self.max_len:
#         #     self.buff.pop(0)

#         def dfs(i, cur):
#             if i == len(self.buff):
#                 return '*' in cur
            
#             if self.buff[i] not in cur:
#                 return False
            
#             return dfs(i + 1, cur[self.buff[i]])
        
#         # self.buff = ['a','b']
#         return dfs(0, self.root)
        
        
        # for i in range(len(self.buff)):
        #     if self.buff[i] in self.root:
        #         # print(i)
        #         # print(i,self.buff[i:])
        #         if dfs(i, self.root) == True:
        #             return True
        # return False
    
class TrieNode:
    def __init__(self):
        self.dic = {}
        self.end = False
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = TrieNode()
        for word in words:
            word = \"\".join(reversed(word))
            self.addword(word)
        self.stream = \"\"
            
    def addword(self, word):
        current = self.root
        for char in word:
            if char not in current.dic:
                current.dic[char] = TrieNode()
            current = current.dic[char]
        current.end = True
            
    def helper(self, current, stream):
        for i in range(len(stream)):
            if stream[i] not in current.dic: 
                if current.end:
                    return True
                else:
                    return False
            else:
                if current.end:
                    return True
            current = current.dic[stream[i]]
        return current.end
        
    def query(self, letter: str) -> bool:
        self.stream = letter + self.stream
        return self.helper(self.root, self.stream)      

        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.p = []
        for w in words:
            self.insert(w)
    
    def insert(self, w):
        p = self.trie
        for c in w:
            if c in p:
                p = p[c]
            else:
                p[c] = {}
                p = p[c]
        p['#'] = ''

    def query(self, letter: str) -> bool:
        self.p.append(self.trie)
        p2 = []
        for p in self.p:
            if letter in p:
                p2.append(p[letter])
        self.p = p2
        return any('#' in p for p in self.p)
                


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
    def __init__(self, words: List[str]):
            self.dic={}
            for i in words:
                cur=self.dic
                for j in i[::-1]:
                    if j not in cur:
                        cur[j]={}
                        cur=cur[j]
                    else:
                        cur=cur[j]
                cur['#']={}
            self.res=[]
                    
    def query(self, letter: str) -> bool:
        self.res.append(letter)
        cur=self.dic
        for i in self.res[::-1]:
            if i not in cur:
                return False
            if '#' in cur[i]:
                return True
            if i in cur:
                cur=cur[i]
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = self.create_trie(words)
        self.l = []

    def create_trie(self, words):
        trie = {}
        for word in words:
            curr = trie
            for ch in word:
                if ch not in curr:
                    curr[ch] = {}
                curr = curr[ch]
            curr['.'] = True
        return trie
            
        
    def query(self, letter: str) -> bool:
        self.l.append(self.trie)
        self.l = [trie[letter] for trie in self.l if letter in trie]
        return any('.' in trie for trie in self.l)
                
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    def __init__(self, c: str, is_word: bool):
        self.c = c
        self.next_chars = {}
        self.is_word = is_word 
    def traverse(self, c):
        if c in self.next_chars:
            return self.next_chars[c]
        return None

    def add(self, c, is_word):
        if c not in self.next_chars:
            self.next_chars[c] = Trie(c, is_word)
        return self.next_chars[c]
    
class StreamChecker:
            
    def __init__(self, words: List[str]):
        self.tr = Trie(\"\", False)
        self.iters = []
        
        for word in words:
            cur = self.tr
            for c in word[::-1]:
                cur = cur.add(c, False)
            cur.is_word = True

    def query(self, letter: str) -> bool:
        self.iters.append(letter)
        cur = self.tr
        for c in self.iters[::-1]:
            cur = cur.traverse(c)
            if not cur:
                return False
            if cur.is_word:
                return True
            
        return False
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.nodes = []
        for word in words:
            node = self.trie
            for char in word:
                if char not in node:
                    node[char] = {}
                node = node[char]
            node['end'] = True
    def query(self, letter: str) -> bool:
        self.nodes.append(self.trie)
        temp = False
        new_nodes = []
        for node in self.nodes:
            if letter in node:
                node = node[letter]
                if 'end' in node:
                    temp = True
                new_nodes.append(node)
        self.nodes = new_nodes
        return temp


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            node = self.trie
            for char in word:
                if char not in node:
                    node[char] = {}
                node = node[char]
            node['#'] = {}
        self.waiting = []

    def query(self, letter):
        \"\"\"
        :type letter: str
        :rtype: bool
        \"\"\"
        # self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        waiting = []
        for node in self.waiting + [self.trie]:
            if letter in node:
                waiting.append(node[letter])
        self.waiting = waiting
        return any('#' in node for node in self.waiting)
                


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = {}
        
        for word in words:
            curnode = self.root
            for ch in word:
                if ch not in curnode:
                    curnode[ch] = {}
                curnode = curnode[ch]
            curnode['is_end'] = True
        
        self.leads = [self.root] # the pointers to the threads we follow right now

    def query(self, letter: str) -> bool:
        next_leads = [self.root]
        found_word = False
        
        for lead in self.leads:
            if letter in lead:
                new_lead = lead[letter]
                next_leads.append(new_lead)
                if 'is_end' in new_lead:
                    found_word = True
            
        self.leads = next_leads
        return found_word
    
    
    
# class TrieNode:
#     def __init__(self, is_end=False):
#         self.children = {}  # char to trie node
#         self.is_end = is_end

# class StreamChecker:

#     def __init__(self, words: List[str]):
#         self.root = TrieNode()
        
#         for word in words:
#             curnode = self.root
#             for ch in word:
#                 if ch not in curnode.children:
#                     curnode.children[ch] = TrieNode()
#                 curnode = curnode.children[ch]
            
#             curnode.is_end = True
        
#         self.leads = set([self.root]) # the pointers to the threads we follow right now

#     def query(self, letter: str) -> bool:
#         next_leads = set([self.root])
#         found_word = False
        
#         for lead in self.leads:
#             if letter in lead.children:
#                 next_leads.add(lead.children[letter])
#                 if lead.children[letter].is_end:
#                     found_word = True
            
#         self.leads = next_leads
#         return found_word


class TrieNode:
    def __init__(self, eow):
        self.children = {}
        self.eow = eow

class Trie:
    def __init__(self):
        self.root = TrieNode(False)

    def add(self, word):
        cur = self.root
        for ch in word:
            if ch not in cur.children:
                cur.children[ch] = TrieNode(False)

            cur = cur.children[ch]

        cur.eow = True

class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie = Trie()
        for word in words:
            self.trie.add(word)

        self.trie_curs = [self.trie.root]

    def query(self, letter: str) -> bool:
        trie_curs_new = [self.trie.root]
        hit = False
        for cur in self.trie_curs:
            if letter in cur.children:
                trie_curs_new.append(cur.children[letter])
                if not hit and cur.children[letter].eow:
                    hit = True

        self.trie_curs = trie_curs_new

        return hit

class StreamChecker:
    def __init__(self, words: List[str]):
        self.dic={}
        for i in words:
            cur=self.dic
            for j in i[::-1]:
                if j not in cur:
                    cur[j]={}
                    cur=cur[j]
                else:
                    cur=cur[j]
            cur['#']={}
        self.res=[]
                    
    def query(self, letter: str) -> bool:
        self.res.append(letter)
        cur=self.dic
        for i in self.res[::-1]:
            if i not in cur:
                return False
            if '#' in cur[i]:
                return True
            if i in cur:
                cur=cur[i]
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.memo = defaultdict(dict)
        self.words = set()
        words_ = [word[::-1] for word in set(words)]
        for word in words_:
            for i in range(len(word)-1):
                self.memo[i+1][word[:i+1]]=0
        
        for word in words_:
            self.memo[len(word)][word]=1     
        
        self.hist = []
        
        #print(self.memo)
    
    def query(self, letter: str) -> bool:
        self.hist.append(letter)
        w = ''
        for i in range(len(self.hist)-1,-1,-1):
            w+=self.hist[i]
            #print(w)
            c = self.memo[len(w)].get(w,None)
            if c is None:
                return False
            if c:
                return True
            
        return False


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.nodes = []
        for word in words:
            node = self.trie
            for char in word:
                if char not in node:
                    node[char] = {}
                node = node[char]
            node['end'] = True

    def query(self, letter: str) -> bool:
        self.nodes.append(self.trie)
        temp = False
        new_nodes = []
        
        for node in self.nodes:
            if letter in node:
                node = node[letter]
                if 'end' in node:
                    temp = True
                new_nodes.append(node)
        self.nodes = new_nodes
        return temp


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.flag = []
        self.trie = {}
        for word in words:
            cur = self.trie
            for c in word:
                if c not in cur:
                    cur[c] = {}
                cur = cur[c]
            cur['.'] = {}


    def query(self, letter: str) -> bool:
        if letter in self.trie:
            self.flag.append(self.trie)
        res = False
        new_flag = []
        for f in self.flag:
            if letter in f:
                new_flag.append(f[letter])
                if '.' in f[letter]:
                    res = True
        self.flag = new_flag
        return res


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = self.buildTrie(words)
        self.nodes = [self.trie]
    
    def buildTrie(self, words):
        trie = {}
        for word in words:
            curr = trie
            for char in word:
                if char not in curr:
                    curr[char] = {}
                curr = curr[char]
            curr['isWord'] = True
        return trie

    def query(self, letter: str) -> bool:
        found = False
        newNodes = [self.trie]
        for i,node in enumerate(self.nodes):
            if letter in node:
                if 'isWord' in node[letter]:
                    found = True
                    if len(list(node[letter].keys())) > 1:
                        newNodes.append(node[letter])
                else:
                    newNodes.append(node[letter])
        self.nodes = newNodes
        return found
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    def __init__(self):
        self.chars = {}
        self.isEnd = False
        self.current = self
        self.pointers = set([self])
        
    def add(self, word):
        trie = self
        for c in word:
            if c not in trie.chars:
                trie.chars[c] = Trie()
            trie = trie.chars[c]
        trie.isEnd = True
        
    def searchNext(self, char):
        newPointers = set([self])
        isWord = False
        for pointer in self.pointers:
            if char in pointer.chars:
                newPointer = pointer.chars[char]
                if newPointer.isEnd:
                    isWord = True
                newPointers.add(newPointer)
        self.pointers = newPointers
        return isWord
            

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        for word in words:
            self.trie.add(word)
        

    def query(self, letter: str) -> bool:
        return self.trie.searchNext(letter)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            cur = self.trie
            for char in word:
                if char not in cur:
                    cur[char] = {}
                cur = cur[char]
            cur['#'] = {}
        
        self.candidates = deque()
    def query(self, letter: str) -> bool:
        size = len(self.candidates)
        for i in range(size):
            candidate = self.candidates.popleft()
            if letter in candidate:
                self.candidates.append(candidate[letter])
        if letter in self.trie:
            self.candidates.append(self.trie[letter])
        for candidate in self.candidates:
            if '#' in candidate:
                return True
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.suffixTree = {}
        
        for word in set(words):
            node = self.suffixTree
            for ch in word[::-1]:
                if not ch in node:
                    node[ch] = {}
                node = node[ch]
            node['$'] = True
            # print(word,self.suffixTree)
        self.queries = []
        # print(self.suffixTree)
            
        # print(self.letters)
        return 

    def query(self, letter: str) -> bool:
        self.queries.append(letter)
        node = self.suffixTree
        # word = self.queries[::]
        # # print(''.join(self.queries))
        # while len(word)>0:
        #     ch = word.pop()
        for ch in self.queries[::-1]:
            # print(ch)
            if '$' in node:
                return True
            if not ch in node:
                return False
            else:
                node = node[ch]
            
        # print(letter,''.join(self.queries),node,'$' in node)
        return '$' in node
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.children = {}

class Trie:

    def __init__(self):
        \"\"\"
        Initialize your data structure here.
        \"\"\"
        self.root = TrieNode()
        
    def insert_suffix(self, word, node):
        if word == '':
            return
        if word[0] not in node.children:
            node.children[word[0]] = TrieNode()
        self.insert_suffix(word[1:], node.children[word[0]])

    def insert(self, word):
        \"\"\"
        Inserts a word into the trie.
        \"\"\"
        word = word + '$'
        self.insert_suffix(word, self.root)
        
    def print_subtree(self, node):
        print(list(node.children.keys()))
        for child in node.children.values():
            self.print_subtree(child)
            
    def __str__(self):
        self.print_subtree(self.root)

class StreamChecker:

    def __init__(self, words):
        self.Trie = Trie()
        for word in words:
            self.Trie.insert(word)
        # print(self.Trie)
        self.matches = [self.Trie.root] # a list of nodes which represent terminal letters of all the currently active partial matches
        
    def query(self, letter):
        found_match = False
        extended_matches = [self.Trie.root]
        for match in self.matches:
            if letter in match.children:
                new_match = match.children[letter]
                if '$' in new_match.children:
                    found_match = True
                extended_matches.append(new_match)
        self.matches = extended_matches
        # print(self.matches)
        return found_match
            
      

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = defaultdict(dict)
        for word in words:
            cur = self.trie
            for letter in word:
                if letter not in cur: cur[letter] = {}
                cur = cur[letter]
            cur[\"#\"] = True
        self.point = deque()
        
    def query(self, letter: str) -> bool:
        temp = deque()
        self.point.append(self.trie)
        for pt in self.point:
            if letter in pt:
                temp.append(pt[letter])
        self.point = temp
        
        for pt in self.point:
            if \"#\" in pt:
                return True
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.stream = deque([])

        for word in set(words):
            node = self.trie       
            for ch in word[::-1]:
                if not ch in node:
                    node[ch] = {}
                node = node[ch]
            node['$'] = word

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        node = self.trie
        for ch in self.stream:
            if '$' in node:
                return True
            if not ch in node:
                return False
            node = node[ch]
        return '$' in node


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.stream = deque([])
        
        for word in set(words): 
            node = self.trie
            for ch in word[::-1]:# for each word start from root node
                if ch not in node:
                    node[ch]= {}
                node = node[ch]
            node['$']= word
            
    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        
        node = self.trie
        for ch in self.stream:
            if '$' in node:
                return(True)
            if ch not in node:
                return(False)
            node = node[ch]
            
        return('$' in node)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode():
    def __init__(self):
        self.children = {}
        self.isEnd = False

class Trie():
    def __init__(self):
        self.root = TrieNode()
    
    def insert(self, word):
        node = self.root
        for char in word:
            if char not in node.children:
                node.children[char] = TrieNode()
            node = node.children[char]
        node.isEnd = True

class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.maxlen = len(words)
        self.cache = ''
        for w in words:
            self.trie.insert(w[::-1])
        
    def query(self, letter: str) -> bool:
        self.cache += letter
        # self.result = False
        k = 1
        node = self.trie.root
        while k <= len(self.cache):
            char = self.cache[-k]
            if char in node.children:
                if node.children[char].isEnd:
                # self.result = self.result or node.children[char].isEnd
                    return True
                k += 1
                node = node.children[char]
            else:
                return False
        # return self.result
 

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.children = {}
        self.isWord = False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = TrieNode()
        self.letters = \"\"
        
        for word in words:
            self.insertWord(word)

            
    def insertWord(self, word):
        node = self.root
        word = word[::-1]
        for ch in word:
            if ch not in node.children:
                node.children[ch] = TrieNode()
            node = node.children[ch]
        node.isWord = True
        
        
    def query(self, letter: str) -> bool:
        self.letters += letter
        k = 0
        n = len(self.letters)
        node = self.root
        
        for i in range(n-1, -1, -1):
            ch = self.letters[i]
            k += 1
            if ch not in node.children:
                return False
            
            node = node.children[ch]
            if k>0 and node.isWord:
                return True
        return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self):
        self.children = {}
        self.isWord = False
        
class Trie:
    def __init__(self):
        self.root = TrieNode()
        
    def add(self, word):
        p = self.root
        for c in word:
            if c not in p.children:
                p.children[c] = TrieNode()
            p = p.children[c]
        p.isWord = True
        
    # def search(self, word):
    #     p = self.root
    #     for c in word:
    #         if c not in p.children:
    #             return False
    #         p = p.children[c]
    #     return p.isWord
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.queries = []
        self.trie = Trie()
        for word in words:
            self.trie.add(word[::-1])
        

    def query(self, letter: str) -> bool:
        self.queries.append(letter)
        p = self.trie.root
        for i in range(len(self.queries)-1, -1, -1):
            c = self.queries[i]
            if c not in p.children:
                return False
            p = p.children[c]
            if p.isWord:
                return True
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.dic = {}
        self.end = False
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = TrieNode()
        for word in words:
            word = \"\".join(reversed(word))
            self.addword(word)
        self.stream = \"\"
            
    def addword(self, word):
        current = self.root
        for char in word:
            if char not in current.dic:
                current.dic[char] = TrieNode()
            current = current.dic[char]
        current.end = True
            
    def helper(self, current, stream):
        for i in range(len(stream)):
            if stream[i] not in current.dic: 
                if current.end:
                    return True
                else:
                    return False
            else:
                if current.end:
                    return True
            current = current.dic[stream[i]]
        return current.end
        
    def query(self, letter: str) -> bool:
        self.stream = letter + self.stream
        return self.helper(self.root, self.stream)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for w in words:
            cur = self.trie
            for l in reversed(w):
                if l not in cur:
                    cur[l] = {}
                cur = cur[l]
            cur[\"#\"] = True
        self.stream = deque()

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        #print(self.stream)
        cur = self.trie
        for l in self.stream:
            #print(l)
            if l in cur:
                cur = cur[l]
                #print(\"cur:\",cur)
            else:
                break
            if \"#\" in cur: return True
        return False

class TrieNode:

    def __init__(self):
        self.dic = defaultdict(TrieNode)
        self.isWord = False

    def addWord(self, word):
        node = self
        for char in word:
            if not node.dic[char]:
                node.dic[char] = TrieNode()
            node = node.dic[char]
        node.isWord = True


class StreamChecker:

    def __init__(self, words):
        self.root = TrieNode()
        self.stream = \"\"
        for word in words:
            self.root.addWord(word[::-1])

    def query(self, letter: str) -> bool:
        self.stream += letter
        node = self.root
        i = len(self.stream) - 1
        while i >= 0 and self.stream[i] in node.dic:
            node = node.dic[self.stream[i]]
            if node.isWord:
                return True
            i -= 1
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

# Written with love by atm1504
class TrieNode:
    def __init__(self):
        self.children={}
        self.isWord=False
class StreamChecker:
    def __init__(self, words: List[str]):
        self.root=TrieNode()
        self.letters=\"\"
        
        for word in words:
            self.insertWord(word)
        
    def insertWord(self,word):
        node=self.root
        word=word[::-1]
        for x in word:
            if x not in node.children:
                node.children[x]=TrieNode()
            node=node.children[x]
        node.isWord=True
        
    def query(self, letter: str) -> bool:
        self.letters+=letter
        k=0
        n=len(self.letters)
        node=self.root
        for i in range(n-1,-1,-1):
            x=self.letters[i]
            k+=1
            if x not in node.children:
                return False
            node=node.children[x]
            if k>0 and node.isWord:
                return True
        return False

class TrieNode:
    def __init__(self):
        self.children={}
        self.isWord=False
class StreamChecker:

    def __init__(self, words: List[str]):
        self.root=TrieNode()
        self.letters=\"\"
        
        for word in words:
            self.insertWord(word)
        
    def insertWord(self,word):
        node=self.root
        word=word[::-1]
        for x in word:
            if x not in node.children:
                node.children[x]=TrieNode()
            node=node.children[x]
        node.isWord=True
        
    def query(self, letter: str) -> bool:
        self.letters+=letter
        k=0
        n=len(self.letters)
        node=self.root
        for i in range(n-1,-1,-1):
            x=self.letters[i]
            k+=1
            if x not in node.children:
                return False
            node=node.children[x]
            if k>0 and node.isWord:
                return True
            
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.stream = deque([])

        for word in set(words):
            node = self.trie  
            for ch in word[::-1]:
                if ch not in node:
                    node[ch] = {}
                node = node[ch]
            node['$'] = word
        
        print((self.trie))
        
        
    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        
        node = self.trie
        for ch in self.stream:
            if '$' in node:
                return True
            if not ch in node:
                return False
            node = node[ch]
        return '$' in node

 
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.children = [None]*26
        self.isEnd = False
        self.word = \"\"
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.stream = \"\"
        self.root = TrieNode()
        self.maxL = 0
        for word in words:
            self.maxL = max(self.maxL, len(word))
            self.add(word)
    
    def add(self, word):
        p = self.root
        for c in word[::-1]:
            idx = ord(c) - ord('a')
            if not p.children[idx]:
                p.children[idx] = TrieNode()
            p = p.children[idx]
        p.isEnd = True
        p.word = word
        

    def query(self, letter: str) -> bool:
        if len(self.stream) < self.maxL:
            self.stream = letter + self.stream   # ba
        else:
            self.stream = self.stream[:-1]
            self.stream = letter + self.stream 
      
        p = self.root 
        for c in self.stream:
            idx = ord(c) - ord('a')
            if not p.children[idx]:
                return False
            if p.children[idx].isEnd:
                return True
            p = p.children[idx]
    
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = dict()
        self.input = ''
        
        for word in words:
            ptr = self.trie
            for w in word[::-1]:
                if w not in list(ptr.keys()): 
                    ptr[w] = dict()
                ptr = ptr[w]
            ptr['$'] = word


            
        

    def query(self, letter: str) -> bool:
        self.input += letter
        node = self.trie
        for index in range(len(self.input)):
            ch = self.input[-(index+1)]
            # print(' index:', ch, 'dict:', node.keys())
            if '$' in list(node.keys()):
                return True
            elif ch not in list(node.keys()):
                return False
            node = node[ch]
        return '$' in list(node.keys())
                
            
                
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self, c):
        self.c = c
        self.children = {}
        self.is_word = False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.char_list = []
        self.trie = TrieNode('')
        for word in words:
            node = self.trie
            for c in word[::-1]:
                if c not in node.children:
                    node.children[c] = TrieNode(c)
                node = node.children[c]
            node.is_word = True

    def query(self, letter: str) -> bool:
        self.char_list.append(letter)
        i = len(self.char_list) - 1
        node = self.trie
        while i >= 0:
            if self.char_list[i] not in node.children:
                break
            node = node.children[self.char_list[i]]
            if node.is_word:
                return True
            i -= 1
        return node.is_word


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.children = {}
        self.isend_word = False

        
class Trie:
    def __init__(self):
        self.root = TrieNode()
    
    
    def insert(self, word):
        curr = self.root
        for c in word:
            if c not in curr.children:
                curr.children[c] = TrieNode()
            curr = curr.children[c]
        curr.isend_word = True
        
        
class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.search = []
        for word in words:
            self.trie.insert(word[::-1])
        
        
    def query(self, letter: str) -> bool: 
        self.search.append(letter)
        curr = self.trie.root
        for i in range(len(self.search) - 1, -1, -1):
            char = self.search[i]
            if curr.isend_word:
                return True
            if char not in curr.children:
                return False
            curr = curr.children[char]
        
        return curr.isend_word


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode():
    def __init__(self):
        self.children = collections.defaultdict(TrieNode) 
        self.isEnd = False

class Trie():
    def __init__(self):
        self.root = TrieNode()
    
    def insert(self, word):
        node = self.root
        for char in word:
            node = node.children[char]
        node.isEnd = True

class StreamChecker:
    def __init__(self, words: List[str]):
        self.letters = []
        self.trie = Trie()
        for w in words:
            self.trie.insert(w[::-1])
        
    def query(self, letter: str) -> bool:
        self.letters.append(letter)
        i = len(self.letters) - 1
        node = self.trie.root
        while i >= 0:
            if node.isEnd:
                return True
            if self.letters[i] not in node.children:
                return False
            node = node.children[self.letters[i]]
            i -= 1
        return node.isEnd


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode():
    def __init__(self):
        self.children = {}
        self.isEnd = False

class Trie():
    def __init__(self):
        self.root = TrieNode()
    
    def insert(self, word):
        node = self.root
        for char in word:
            if char not in node.children:
                node.children[char] = TrieNode()
            node = node.children[char]
        node.isEnd = True

class StreamChecker:
    def __init__(self, words: List[str]):
        self.letters = []
        self.trie = Trie()
        for w in words:
            self.trie.insert(w[::-1])
        
    def query(self, letter: str) -> bool:
        self.letters.append(letter)
        i = len(self.letters) - 1
        node = self.trie.root
        while i >= 0:
            if node.isEnd:
                return True
            if self.letters[i] not in node.children:
                return False
            node = node.children[self.letters[i]]
            i -= 1
        return node.isEnd


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self,letter):
        self.letter=letter
        self.next_alpha={}
        self.end=False

class StreamChecker:

    def __init__(self, words: List[str]):

        self.root=TrieNode('root')
        self.stream=deque()

        self.p=None
        
        for word in words:
            buffer=TrieNode('a')
            if(len(word)==1):
                self.root.next_alpha[word[0]]=TrieNode(word[0])
                self.root.next_alpha[word[0]].end=True
                continue
                
            for letter_ind,l in enumerate(word[::-1]):
                if(letter_ind==0):
                    if(l not in list(self.root.next_alpha.keys())):
                        self.root.next_alpha[l]=TrieNode(l)
                        
                    buffer=self.root.next_alpha[l]
                    continue
                
                if(l in list(buffer.next_alpha.keys())):
                    buffer=buffer.next_alpha[l]
                else:
                    
                    nex=TrieNode(l)
                    buffer.next_alpha[l]=nex
                    buffer=nex
                
                
                if(letter_ind==len(word)-1):
                    buffer.end=True
        
        
    def query(self, letter: str) -> bool:

        self.stream.appendleft(letter)
        cur=self.root
        
        for c in self.stream:
            if c in cur.next_alpha:
                cur = cur.next_alpha[c]
                if cur.end: return True
            else: break
        return False
            
            
        '''
        print(letter,end=\"->\")
        if(self.p==None):
            if(letter not in self.root.next_alpha.keys()):
                return False
            
            self.p=self.root.next_alpha[letter]
            
            
                
        else:
            if(letter in self.p.next_alpha.keys()):
                self.p=self.p.next_alpha[letter]
                print(\"next\")
            else:
                if(letter not in self.root.next_alpha.keys()):
                    return False
                self.p=self.root.next_alpha[letter]
                print(\"reset\")

            

        print(self.p.end)
        return self.p.end

        '''
        
        

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    

    def __init__(self, words):
        self.words = []
        self.store = {}
        self.stack = ''
        self.sample = 25
        for w in words:
            if not w:
                continue
            self.insertStore(w[::-1], self.store)

    def query(self, letter):
        self.stack += letter
        return self.queryStore(self.stack, self.store)

    def insertStore(self, w, store):
        if w[:self.sample] not in store:
            store[w[:self.sample]] = {}
        if len(w) <= self.sample:
            store[w[:self.sample]]['!'] = None
        else:
            self.insertStore(w[self.sample:], store[w[:self.sample]])

    def queryStore(self, stack, store):
        if not stack:
            return False
        s = stack[:-self.sample-1:-1]
        if s in store:
            if '!' in store[s]:
                return True
            if self.queryStore(stack[:-self.sample], store[s]):
                return True
        for i in range(1, self.sample):
            if s[:i] in store:
                return True
        return False





class StreamChecker:
    def __init__(self, words: List[str]):
        self.root = {}
        # self.max_len = 0
        self.buff = \"\"
        for word in words:
            # self.max_len = max(self.max_len , len(word))
            cur = self.root
            
            for w in word[::-1]:
                cur = cur.setdefault(w, {})
            cur['*'] = '*'
            
        # print(self.root)
            
    
        
        

    def query(self, letter: str) -> bool:
        self.buff = letter + self.buff 
        # if len(self.buff) > self.max_len:
        #     self.buff.pop(0)

        def dfs(i, cur):
            if i == len(self.buff):
                return '*' in cur
            
            if '*' in cur:
                return True
            
            if self.buff[i] not in cur:
                return False
            
            return dfs(i + 1, cur[self.buff[i]])
        
        # self.buff = ['a','b']
        # print(self.buff)
        return dfs(0, self.root)
        
        
        # for i in range(len(self.buff)):
        #     if self.buff[i] in self.root:
        #         # print(i)
        #         # print(i,self.buff[i:])
        #         if dfs(i, self.root) == True:
        #             return True
        # return False
    
# class TrieNode:
#     def __init__(self):
#         self.dic = {}
#         self.end = False
        
# class StreamChecker:

#     def __init__(self, words: List[str]):
#         self.root = TrieNode()
#         for word in words:
#             word = \"\".join(reversed(word))
#             self.addword(word)
#         self.stream = \"\"
            
#     def addword(self, word):
#         current = self.root
#         for char in word:
#             if char not in current.dic:
#                 current.dic[char] = TrieNode()
#             current = current.dic[char]
#         current.end = True
            
#     def helper(self, current, stream):
#         for i in range(len(stream)):
#             if stream[i] not in current.dic: 
#                 if current.end:
#                     return True
#                 else:
#                     return False
#             else:
#                 if current.end:
#                     return True
#             current = current.dic[stream[i]]
#         return current.end
        
#     def query(self, letter: str) -> bool:
#         self.stream = letter + self.stream
#         return self.helper(self.root, self.stream)      

        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode():
    def __init__(self):
        self.children = {}
        self.isEnd = False
        
class Trie():
    def __init__(self):
        self.root = TrieNode()
    
    def insert(self, word):
        node = self.root
        for char in word:
            if char not in node.children:
                node.children[char] = TrieNode()
            node = node.children[char]
        node.isEnd = True
        
class StreamChecker:
    def __init__(self, words: List[str]):
        self.letters = []
        self.trie = Trie()
        for w in words:
            self.trie.insert(w[::-1])

    def query(self, letter: str) -> bool:
        self.letters.append(letter)
        i = len(self.letters) - 1
        node = self.trie.root
        while i >= 0:
            if node.isEnd:
                return True
            if self.letters[i] not in node.children:
                return False
            node = node.children[self.letters[i]]
            i -= 1
        return node.isEnd


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.stream = deque([])

        for word in set(words):
            node = self.trie       
            for ch in word[::-1]:
                if not ch in node:
                    node[ch] = {}
                node = node[ch]
            node['$'] = word
        
        
    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        
        node = self.trie
        for ch in self.stream:
            if '$' in node:
                return True
            if not ch in node:
                return False
            node = node[ch]
        return '$' in node

class StreamChecker_TLE:
    
    def _reinit(self):
        newdict = collections.defaultdict(list)
        for w in self.words:
            newdict[w[0]].append((w, 0))
        return newdict

    def __init__(self, words: List[str]):
        self.words = words
        self.curdict = self._reinit()
        self.refdict = self._reinit()

    def query(self, letter: str) -> bool:
        if not self.curdict[letter]:
            self.curdict = self._reinit()
            return False
        expect = self.curdict[letter][:]
        self.curdict = self._reinit()
        ret = False
        for w, idx in expect:
            idx += 1
            if idx == len(w):
                ret = True
            else:
                nxtch = w[idx]
                self.curdict[nxtch].append((w, idx))
        return ret
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.children, self.end_node = {}, 0
         
class Trie:
    def __init__(self):
        self.root = TrieNode()

    def insert(self, word):
        root = self.root
        for symbol in word:
            root = root.children.setdefault(symbol, TrieNode())
        root.end_node = 1

class StreamChecker:
    def __init__(self, words):
        self.trie = Trie()
        self.Stream = deque()
        for word in words: self.trie.insert(word[::-1])
         
    def query(self, letter):
        self.Stream.appendleft(letter)
        cur = self.trie.root
        for c in self.Stream:
            if c in cur.children:
                cur = cur.children[c]
                if cur.end_node: return True
            else: break
        return False

            
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import defaultdict
from collections import deque

class TrieNode:
    def __init__(self):
        self.is_word = False  # flag for complete word
        self.children = defaultdict(TrieNode)  # dictionary to store children TrieNodes

class Trie:
    def __init__(self, words=None):
        self.root = TrieNode()
        if words:
            for word in words:
                self.insert(word)
    
    def insert(self, word):
        curr = self.root
        for char in word:
            curr = curr.children[char]
        
        curr.is_word = True
    
    def search(self, word):
        curr = self.root
        for char in word:
            if curr.children.get(char, None) is None:
                return False
            curr = curr.children[char]
        return curr.is_word
    
    def starts_with(self, prefix):
        # prefix can be a string as well as a list of chars
        curr = self.root
        for char in prefix:
            if curr.children.get(char, None) is None:
                return False
            curr = curr.children[char]
        return True
    
    def contains_stream(self, stream, index=0):
        # stream can be a string as well as a list of chars
        curr = self.root
        while index < len(stream):
            if curr.is_word:
                return True
            char = stream[index]
            if curr.children.get(char, None) is None:
                return False
            curr = curr.children[char]
            index += 1
        return curr.is_word
    
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        # add words in reverse
        for word in words:
            self.trie.insert(word[::-1])
        
        # for word in words:
        #     print(self.trie.search(word[::-1]))
        
        self.stream = deque()
        

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        return self.trie.contains_stream(self.stream)
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.end = False
        self.children = [None] * 26

class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = TrieNode()
        self.cand = []
        self.maxlen = float('-inf')
        for w in words:
            self.insert(w)
            self.maxlen = max(self.maxlen, len(w))
            
    def insert(self, s):
        node = self.root
        for c in s[::-1]:
            index = ord(c)-ord('a')
            if node.children[index] is None:
                node.children[index] = TrieNode()
            node = node.children[index]
        node.end = True

    def query(self, letter: str) -> bool:
        self.cand.insert(0, letter)
        
        if len(self.cand) > self.maxlen:
            self.cand.pop()
        
        curr = self.root
        
        for c in self.cand:
            if curr.children[ord(c)-ord('a')] is not None:
                curr = curr.children[ord(c)-ord('a')]
                if curr.end:
                    return True
            else:
                return False
            
        return False       


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import deque   
class TrieNode:
    def __init__(self):
        self.children, self.end_node = {}, 0

class Trie:
    def __init__(self):
        self.root = TrieNode()
    
    def insert(self, word):
        root = self.root
        for symbol in word:
            root = root.children.setdefault(symbol, TrieNode())
        root.end_node = 1
     
class StreamChecker:
    ## trie, reverse?
    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.Stream = deque()
        for word in words:
            self.trie.insert(word[::-1])
        # self.arr = [0] * 26
        # for word in words:
        #     # for l in word:
        #     self.arr[ord(word[-1])-ord('a')] += 1

    def query(self, letter: str) -> bool:
        # res = self.arr[ord(letter) - ord('a')] > 0
        # self.arr[ord(letter) - ord('a')] -= 1
        # return res
        self.Stream.appendleft(letter)
        cur = self.trie.root
        for c in self.Stream:
            if c in cur.children:
                cur = cur.children[c]
                if cur.end_node == 1:
                    return True
            else:
                break
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import deque


class TrieNode:
    def __init__(self):
        self.children = {}
        self.is_leaf = False


class Trie:
    def __init__(self):
        self.root = TrieNode()

    def insert(self, word):
        root = self.root
        for c in word:
            root = root.children.setdefault(c, TrieNode())
        root.is_leaf = True


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.stream = deque()
        for word in words:
            self.trie.insert(word[::-1])

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        curr = self.trie.root
        for c in self.stream:
            if c in curr.children:
                curr = curr.children[c]
                if curr.is_leaf:
                    return True
            else:
                return False

class TrieNode:
    def __init__(self):
        self.children, self.end_node = {}, 0
         
class Trie:
    def __init__(self):
        self.root = TrieNode()

    def insert(self, word):
        root = self.root
        for symbol in word:
            root = root.children.setdefault(symbol, TrieNode())
        root.end_node = 1

class StreamChecker:
    def __init__(self, words):
        self.trie = Trie()
        self.Stream = deque()
        for word in words: self.trie.insert(word[::-1])
         
    def query(self, letter):
        self.Stream.appendleft(letter)
        cur = self.trie.root
        for c in self.Stream:
            if c in cur.children:
                cur = cur.children[c]
                if cur.end_node: return True
            else: break
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.children, self.end_node = {}, 0
         
class Trie:
    def __init__(self):
        self.root = TrieNode()

    def insert(self, word):
        root = self.root
        for symbol in word:
            root = root.children.setdefault(symbol, TrieNode())
        root.end_node = 1

class StreamChecker:
    def __init__(self, words):
        self.trie = Trie()
        self.Stream = deque()
        self.maxLength = len(max(words, key=lambda x: len(x)))
        for word in words: self.trie.insert(word[::-1])
         
    def query(self, letter):
        self.Stream.appendleft(letter)
        if len(self.Stream) > self.maxLength: self.Stream.pop()
        cur = self.trie.root
        for c in self.Stream:
            if c in cur.children:
                cur = cur.children[c]
                if cur.end_node: return True
            else: break
        return False

            
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode():
    def __init__(self):
        self.children = {}
        self.isend = 0

class Trie():
    def __init__(self):
        self.root = TrieNode()
    
    def insert(self, word):
        root = self.root
        for char in word:
            root = root.children.setdefault(char, TrieNode()) # setdefault(key, default=None)
        root.isend = 1


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        
        self.stream = deque()
        
        for word in words:
            self.trie.insert(word[::-1])

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        cur = self.trie.root
        for c in self.stream:
            if c in cur.children:
                cur = cur.children[c]
                if cur.isend: return True
            else:
                break
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    
    def __init__(self):
        self.children = [None for _ in range(26)]
        self.end = False
        
class Trie:
    
    def __init__(self):
        self.root = TrieNode()
        
    def insert(self, word):
        cur = self.root
        for w in word:
            idx = ord(w) - ord('a')
            if not cur.children[idx]:
                cur.children[idx] = TrieNode()
            cur = cur.children[idx]
        cur.end = True

    def match(self, word):
        # print('word = ', word)
        cur = self.root
        for w in word:
            if cur.end: return True
            idx = ord(w) - ord('a')
            if cur.children[idx]:
                cur = cur.children[idx]
            else: return cur.end
        return cur.end 
    
class StreamChecker:

    def __init__(self, words: List[str]):
        self.cache = ''
        self.size = 0
        self.trie = Trie()
        for word in words:
            self.trie.insert(word[::-1])
            self.size = max(self.size, len(word))

    def query(self, letter: str) -> bool:
        self.cache += letter
        if len(self.cache) > self.size:
            self.cache = self.cache[1:]
        return self.trie.match(self.cache[::-1])
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode():
    def __init__(self):
        self.children = collections.defaultdict()
        self.isEnd = False

class Trie():
    def __init__(self):
        self.root = TrieNode()
    
    def insert(self, word):
        node = self.root
        for char in word:
            if char not in node.children:
                node.children[char] = TrieNode()
            node = node.children[char]
        node.isEnd = True

class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.maxlen = 0
        self.cache = []
        for w in words:
            self.trie.insert(w[::-1])
            self.maxlen = max(self.maxlen, len(w))
        
    def query(self, letter: str) -> bool:
        self.cache.append(letter)
        if len(self.cache) > self.maxlen:
            self.cache = self.cache[1:]
        i = len(self.cache) - 1
        node = self.trie.root
        while i >= 0:
            if node.isEnd:
                return True
            if self.cache[i] not in node.children:
                return False
            node = node.children[self.cache[i]]
            i -= 1
        return node.isEnd
 

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.stream = deque([])
        self.trie = {}
        
        for word in words:
            node = self.trie
            for char in word[::-1]:
                if char not in node:
                    node[char] = {}
                node = node[char]
            node['$'] = word
    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        node = self.trie
        for char in self.stream:
            if '$' in node:
                return True
            if char not in node:
                return False
            node = node[char]
        
        return '$' in node


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.children = {}
        self.endNode = False
         
class Trie:
    def __init__(self):
        self.root = TrieNode()

    def insert(self, word):
        root = self.root
        for symbol in word:
            root = root.children.setdefault(symbol, TrieNode())
        root.endNode = True

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.Stream = deque()
        for word in words:
            self.trie.insert(word[::-1])

    def query(self, letter: str) -> bool:
        self.Stream.appendleft(letter)
        cur = self.trie.root
        for c in self.Stream:
            if c in cur.children:
                cur = cur.children[c]
                if cur.endNode:
                    return True
            else: 
                break
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        trie = lambda: defaultdict(trie)
        self.trie = trie()
        for word in words:
            current = self.trie
            for ch in word[::-1]:
                current = current[ch]
            current.setdefault(\"#end#\")
        self.stack = []

    def query(self, letter: str) -> bool:
        self.stack.append(letter)
        state_trie = self.trie
        for pos in range(len(self.stack) - 1, -1, -1):
            ch = self.stack[pos]
            if ch in state_trie and \"#end#\" in state_trie[ch]:
                return True
            elif ch not in state_trie:
                return False
            state_trie = state_trie[ch]
        return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self,letter):
        self.letter=letter
        self.next_alpha={}
        self.end=False

class StreamChecker:

    def __init__(self, words: List[str]):

        self.root=TrieNode('root')
        self.stream=deque()

        self.p=None
        
        for word in words:
            buffer=TrieNode('a')
            if(len(word)==1):
                self.root.next_alpha[word[0]]=TrieNode(word[0])
                self.root.next_alpha[word[0]].end=True
                continue
                
            for letter_ind,l in enumerate(word[::-1]):
                if(letter_ind==0):
                    if(l not in list(self.root.next_alpha.keys())):
                        self.root.next_alpha[l]=TrieNode(l)
                        
                    buffer=self.root.next_alpha[l]
                    continue
                
                if(l in list(buffer.next_alpha.keys())):
                    buffer=buffer.next_alpha[l]
                else:
                    
                    nex=TrieNode(l)
                    buffer.next_alpha[l]=nex
                    buffer=nex
                
                
                if(letter_ind==len(word)-1):
                    buffer.end=True
        
        
    def query(self, letter: str) -> bool:

        self.stream.appendleft(letter)
        if(len(self.stream)>=2000):
            self.stream.popleft()
    
        cur=self.root
        
        for c in self.stream:
            if c in cur.next_alpha:
                cur = cur.next_alpha[c]
                if cur.end: return True
            else: break
        return False
            
            
        
        

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:    
    def __init__(self):
        self.children = {}
        self.is_leaf = False
    
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = TrieNode()
        self.root = self.trie
        self.buf = []
        
        for word in words:
            self.trie = self.root
            for i in range(len(word)-1, -1, -1):
                ch = word[i]
                if ch not in self.trie.children:
                    self.trie.children[ch] = TrieNode()
                self.trie = self.trie.children[ch]
            self.trie.is_leaf = True
        

    def query(self, letter: str) -> bool:
        self.buf.append(letter)
        self.trie = self.root
        for i in range(len(self.buf)-1,-1,-1):            
            if self.buf[i] in self.trie.children:
                self.trie = self.trie.children[self.buf[i]]
                if self.trie and self.trie.is_leaf:
                    return True
            else:
                return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    def __init__(self):
        self.child = {}

    def insert(self, word):
        cur_trie = self
        for char in word + '$':  # using $ to indicate end of word
            if char not in cur_trie.child:
                cur_trie.child[char] = Trie()
            cur_trie = cur_trie.child[char]

    def search(self, word):
        cur_trie = self
        for char in word + '$':
            if '$' in cur_trie.child: return True
            if char not in cur_trie.child: return False
            
            cur_trie = cur_trie.child[char]

        return False


class StreamChecker:

    def __init__(self, words):
        self.trie = Trie()
        for word in words:
            self.trie.insert(word[::-1])
        self.buffer = ''

    def query(self, letter: str) -> bool:
        self.buffer = letter + self.buffer
        return self.trie.search(self.buffer) 


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.children = {}
        self.ends_word = False
        
class Trie:
    def __init__(self):
        self.root = TrieNode()
    
    def insert(self, word):
        node = self.root
        for c in word:
            node = node.children.setdefault(c, TrieNode())
        node.ends_word = True

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.deque = deque()
        for w in words:
            self.trie.insert(reversed(w))

    def query(self, letter: str) -> bool:
        self.deque.appendleft(letter)
        if len(self.deque) > 2000:
            self.deque.pop()
        
        node = self.trie.root
        for c in self.deque:
            node = node.children.get(c)
            if not node:
                return False
            if node.ends_word:
                return True
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode: 
    def __init__(self):
        self.children = {}
        self.isWord = False 

class Trie:
    def __init__(self):
        self.root = TrieNode()
    
    def insert(self,word):
        root =self.root 
        for c in word: 
            root= root.children.setdefault(c,TrieNode())  
        root.isWord = True 

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie= Trie() 
        for word in words: self.trie.insert(word[::-1])
        # print(self.trie)
        self.stream = deque()
        

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        curr = self.trie.root
        
        for c in self.stream: 
            if c in curr.children: 
                curr = curr.children[c]
                if curr.isWord : return True 
            else : 
                break
        
        return False 
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


'''
Approach 1:
* Have a dict mapping letters to words ending on that letter.
* Have a list with all the letters queried so far.
* In query(), add letter to the list.
* For each word ending on the queried letter, check if the other letters have been queried as well.

Approach 2:
* Have a trie with words in 'words'.
* Have a list with all letters queried so far.
* Traverse the trie using the letters in the list (scanning backwards).
'''

from collections import defaultdict

class TrieNode:
    
    def __init__(self):
        self.links = dict()
        self.is_word = False
    
    
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie_root = build_trie(words)
        self.queries = []
        
    def query(self, letter: str) -> bool:
        self.queries.append(letter)
        
        index = -1
        node = self.trie_root
        while node.links:
            if index < -len(self.queries):
                break
            letter = self.queries[index]
            if letter not in node.links:
                break
            index -= 1
            node = node.links[letter]
            if node.is_word:
                return True
        return False
            
def build_trie(words):
    root = TrieNode()
    for word in words:
        insert(root, word)
    return root

        
def insert(root, word):
    node = root
    for char in reversed(word):
        if char not in node.links:
            node.links[char] = TrieNode()
        node = node.links[char]
    node.is_word = True

class TreeNode:
    def __init__(self):
        self.children={}
        self.isend=False
class StreamChecker:

    def __init__(self, words: List[str]):
        self.root=TreeNode()
        self.char_so_far=deque()
        for word in words:
            node=self.root
            for char in word[::-1]:
                if char not in node.children:
                    node.children[char]=TreeNode()
                node=node.children[char]
            node.isend=True        
    
    
    def check_word(self,l):
        node=self.root
        for char in l:
            if char not in node.children:
                return False
            node=node.children[char]
            if node.isend:
                return True
        return node.isend    

    def query(self, letter: str) -> bool:
        node=self.root
        self.char_so_far.appendleft(letter)
        return self.check_word(self.char_so_far)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = {'prefix': None, 'dict':None}
        
        #build Trie
        for word in words:
            node = self.root
            for char in word:
                if not char in node:
                    node[char] = {}
                node = node[char]
            node['word'] = True
                    
        #set prefix and dictionary pointers by BFS
        q = collections.deque([self.root])
        while q:
            node = q.popleft()
            for char in node:
                if len(char)==1:
                    child = node[char]
                    extendNode = node['prefix']
                    while extendNode and not char in extendNode:
                        extendNode = extendNode['prefix']
                    if extendNode:
                        child['prefix'] = extendNode[char]
                    else:
                        child['prefix'] = self.root
                    if 'word' in child['prefix']:
                        child['dict'] = child['prefix']
                    else:
                        child['dict'] = child['prefix']['dict']
                    q.append(child)
        
        #self.cur will traverse the Trie
        #while reading the stream
        self.cur = self.root

    def query(self, letter: str) -> bool:
        extendNode = self.cur
        while extendNode and not letter in extendNode:
            extendNode = extendNode['prefix']
        if extendNode:
            self.cur = extendNode[letter]
\t\t\t#checks if current word is in words
\t\t\t#or if the dictionary pointer is non-null
            if 'word' in self.cur or self.cur['dict']: 
                return True
            else:
                return False
        else:
            self.cur = self.root
            return False

        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {} # thought: reverse trie?
        
        self.max_len = 0 # use this as a queue of most recently used stuff
        for word in words:
            pointer = self.trie
            for char in reversed(word):
                if char not in pointer:
                    pointer[char]= {}
                pointer = pointer[char]
            pointer['&'] = True #end character
            self.max_len = max(self.max_len, len(word))
            
        self.queue = deque()
        

    def query(self, letter: str) -> bool:
        self.queue.append(letter)
        if len(self.queue) > self.max_len:
            self.queue.popleft()
        
        pointer = self.trie
        for char in reversed(list(self.queue)):
            if '&' in pointer:
                return True
            if char in pointer:
                pointer = pointer[char]
            else:
                return False
        if '&' in pointer:
            return True
        else:
            return False
            
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import deque

class Trie:
    def __init__(self):
        self.children = [None] * 26
        self.end = False
    
    def insert(self, S):
        t = self
        for c in S:
            if not t.children[ord(c) - ord('a')]:
                t.children[ord(c) - ord('a')] = Trie()
            t = t.children[ord(c) - ord('a')]            
            
        t.end = True
    
    def search(self, stream):
        t = self
        for c in stream:
            if not t.children[ord(c) - ord('a')]:
                return False
            
            t = t.children[ord(c) - ord('a')]
                
            if t.end:
                return True
            
        return False            
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.t = Trie()
        self.stream = deque()        
        for word in words:
            self.t.insert(reversed(word))                
            
    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)        
        return self.t.search(self.stream)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import deque

class TrieNode:
    def __init__(self, val):
        self.end = False
        self.children = {}
        
class Trie:
    
    def __init__(self):
        self.root = TrieNode(-1)
    
    def add(self, word):
        root = self.root
        for ch in word:
            children = root.children
            if children.get(ch) == None:
                child = TrieNode(ch)
                children[ch] = child
                root = child
            else:
                root = children[ch]
        root.end = True
    
    def search(self, word):
        root = self.root
        for val in word:
            if root.children.get(val) == None:
                return False
            else:
                root = root.children[val]
                if root.end:
                    return True
        
class StreamChecker:

    def __init__(self, words: List[str]):
        # self.words = set(words)
        self.Trie = Trie()
        self.maxlen = -1
        for w in words:
            self.maxlen = max(self.maxlen, len(w))
            rev = w[::-1]
            self.Trie.add(rev)
        self.searchArr = deque()
        

    def query(self, letter: str) -> bool:

        self.searchArr.insert(0, letter)
        if len(self.searchArr) > self.maxlen:
            self.searchArr.pop()

        return self.Trie.search(self.searchArr)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Node:
    def __init__(self):
        self.list = [None] * 26
        self.period = False

class Trie:
    def __init__(self):
        self.root = Node()
    
    def add(self, word):
        curr = self.root
        for i in range(len(word) -1, -1, -1):
            letter = word[i]
            asc = ord(letter) - ord('a')
            if not curr.list[asc]:
                curr.list[asc] = Node()
            curr = curr.list[asc]
        curr.period = True
        
    def query(self, word):
        curr = self.root
        for i in range(len(word)-1, -1 ,-1):
            c = word[i]
            asc = ord(c) - ord('a')
            if not curr.list[asc]: return False
            curr = curr.list[asc]
            if curr.period == True: return True
        return False
            
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.query_list = []
        self.words = words
        
        for word in words:
            self.trie.add(word)

    def query(self, letter: str) -> bool:
        self.update_queries(letter)
        return self.trie.query(self.query_list)
        
    
    def update_queries(self, letter):
        self.query_list.append(letter)

    
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
    def __init__(self, words: List[str]):
        self.root = Node(\"\", None)
        for word in words:
            prev = self.root
            substr = \"\"
            for letter in word:
                substr += letter
                is_final = len(substr) == len(word)
                if letter not in prev.children:
                    prev.children[letter] = Node(substr, prev)
                
                curr = prev.children[letter]
                if is_final:
                    curr.is_final = True

                prev = curr

        queue = [self.root]
        while queue:
            curr = queue.pop(0)
            if curr.word:
                letter = curr.word[-1]

                parent_suffix = curr.parent.suffix
                while parent_suffix:
                    if letter in parent_suffix.children:
                        curr.suffix = parent_suffix.children[letter]
                        break
                    else:
                        parent_suffix = parent_suffix.suffix
                if curr.suffix is None:
                    curr.suffix = self.root
                
                suffix = curr.suffix
                while suffix:
                    if suffix.is_final:
                        curr.dictionay_suffix = suffix
                    suffix = suffix.suffix

            for _, child in curr.children.items():
                queue.append(child)

        self.curr = self.root

    def query(self, letter: str) -> bool:
        # print(f\"Input: {letter}\")
        while letter not in self.curr.children:
            if self.curr.suffix:
                self.curr = self.curr.suffix
            else:
                return False
        self.curr = self.curr.children[letter]
        # print(f\"\\tcurr={self.curr.word}\")

        return self.curr.is_final or (self.curr.dictionay_suffix is not None)

    def query_all(self, letters: str) -> List[bool]:
        # self.print_all()
        result = []
        for letter in letters:
            result.append(self.query(letter))
        return result

    def print_all(self):
        queue = [self.root]
        while queue:
            curr = queue.pop(0)
            curr.print()
            for _, child in curr.children.items():
                queue.append(child)


class Node:
    def __init__(self, word, parent):
        self.word = word
        self.parent = parent

        self.is_final = False
        self.children = {}
        self.suffix = None
        self.dictionay_suffix = None

    def print(self):
        final_str = \"*\" if self.is_final else \"\"
        print(f\"({self.word}) {final_str}\")
        for letter, child in self.children.items():
            print(f\"\\t{letter} -> ({child.word})\")
        if self.parent:
            print(f\"\\t[parent] -> ({self.parent.word})\")
        if self.suffix:
            print(f\"\\t[suffix] -> ({self.suffix.word})\")
        dict_suffix_str = f\"({self.dictionay_suffix.word})\" if self.dictionay_suffix else \"None\"
        print(f\"\\t[dict_suffix] -> {dict_suffix_str}\")
        print()


class Trie: 
    def __init__(self):
        self.prev = {}

class StreamChecker:

    def __init__(self, words: List[str]):
        self.t = Trie()
        self.maxlens = 0
        self.backw = ''
        for w in words:
            wn = len(w)
            if wn>self.maxlens:
                self.maxlens = wn
            wt = self.t
            for i in range(wn-1,-1,-1):
                if w[i] not in wt.prev:
                    wt.prev[w[i]] = Trie()
                wt = wt.prev[w[i]]
            wt.prev['$'] = '$'

    def query(self, letter: str) -> bool:
        if len(self.backw)==self.maxlens:
            self.backw = self.backw[1:]
        self.backw += letter            
        wn = len(self.backw)
        wt = self.t
        for i in range(wn-1,-1,-1):
            if self.backw[i] not in wt.prev:
                return False
            wt = wt.prev[self.backw[i]]
            if '$' in wt.prev:
                return True
        return '$' in wt.prev


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import deque

class TrieNode(object):
    __slots__ = [\"children\", \"nextFail\", \"suffixMatches\", \"boundary\"]
    def __init__(self):
        self.children = {}
        self.nextFail = None
        self.suffixMatches = False
        self.boundary = False

    def add(self, word, index=0):
        #print(word)
        if len(word) == index:
            self.boundary = True
            self.suffixMatches = True
            return
        c = word[index]
        if self.children.get(c, None) is None:
            self.children[c] = TrieNode()
        self.children[c].add(word, index + 1)
    def __str__(self):
        return self.__str2()

    def __str2(self, indent=0):
        space = \"  \"*indent
        return \"{}TrieNode(h={}, B={}, nf={},\
{}\".format(
            space,
            hash(self), self.suffixMatches, hash(self.nextFail) if self.nextFail else \"None\", \"\".join(space + k + \": \" + v.__str2(indent+1) + \"\
\" for k, v in self.children.items()),
            space
        ) + space + \")\"


class AhoTrie(object):
    __slots__ = [\"root\"]
    def __init__(self, words):
        self.root = TrieNode()
        for word in words:
            self.root.add(word)
        self.__oho()

    def __oho(self):
        q = deque()
        for c, node in self.root.children.items():
            node.nextFail = self.root
            q.append(node)
        while len(q) > 0:
            node = q.popleft()
            
            for c, child in node.children.items():
                nextFail = node.nextFail
                while not nextFail.children.get(c) and nextFail is not self.root:
                    nextFail = nextFail.nextFail
                if not nextFail.children.get(c):
                    child.nextFail = nextFail
                else:
                    child.nextFail = nextFail.children.get(c)

                q.append(child)
                #child.nextFail = node.nextFail.children.get(c, node.nextFail)
                if  True: #child.suffixMatches:
                    nextFail = child.nextFail
                    while nextFail is not self.root and not nextFail.suffixMatches:
                        nextFail = nextFail.nextFail
                    if nextFail is not self.root:
                        child.suffixMatches = True





class StreamChecker:
    __slots__ = [\"trie\", \"root\", \"cur\"]

    def __init__(self, words: List[str]):
        #print(words)
        self.trie = AhoTrie(words) 
        self.root = self.trie.root
        self.cur = self.root
        #print(self.root)
        

    def query(self, letter: str) -> bool:
        
        
        while not self.cur.children.get(letter) and self.cur is not self.root:
            self.cur = self.cur.nextFail
        #print(hash(self.cur))
        if self.cur.children.get(letter):
            self.cur = self.cur.children[letter]
            temp = self.cur
            #while temp is not self.root:
            if temp.suffixMatches:
                return True
             #  temp = temp.nextFail
        return False
            
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Trie:
    def __init__(self):
        self.next={}
        self.end_here=False
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.root=Trie()
        
        for word in words:
            cur=self.root
            for c in word[::-1]:
                if c not in cur.__next__:
                    cur.next[c]=Trie()
                cur=cur.next[c]
            cur.end_here=True
        self.k=2000
        self.history=deque([])

    def query(self, letter: str) -> bool:
        self.history.append(letter)
        if len(self.history)>self.k:
            self.history.popleft()
            
        if letter not in self.root.__next__:
            return False
        
        n=len(self.history)
        cur=self.root

        for i in range(n):
            c=self.history[n-1-i]
            if c not in cur.__next__:
                return False
            cur=cur.next[c]
            if cur.end_here:
                return True
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.memo = {}
        self.words = set()
        for word in words:
            word_ = word[::-1]
            for i in range(len(word)):
                self.memo[word_[:i+1]]=0
            self.words.add(word_)        
        self.hist = []
        
        print((self.memo))
    
    def query(self, letter: str) -> bool:
        self.hist.append(letter)
        w = ''
        for i in range(len(self.hist)-1,-1,-1):
            w+=self.hist[i]
            #print(w)
            if w not in self.memo:
                return False
            if w in self.words:
                return True
        return False



class TrieNode:
    def __init__(self):
        self.children = {}
        self.is_complete = False

class Trie:
    def __init__(self):
        self.root = TrieNode()
        
    def insert(self, word):
        cur = self.root
        for char in word[: : -1]:
            cur = cur.children.setdefault(char, TrieNode())
        cur.is_complete = True

class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.stream = deque()
        for word in words:
            self.trie.insert(word)

    def query(self, letter: str) -> bool:
        cur = self.trie.root
        self.stream.appendleft(letter)
        for s in self.stream:
            if s in list(cur.children.keys()):
                cur = cur.children[s]
                if cur.is_complete:
                    return True
            else:
                break
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        # time O(h)
        self.stream = deque([])
        self.trie = {}
        
        for word in words:
            node = self.trie
            for char in word[::-1]:
                if char not in node:
                    node[char] = {}
                node = node[char]
            node['$'] = word

    def query(self, letter: str) -> bool:
        # time O(h)
        self.stream.appendleft(letter)
        node = self.trie
        for char in self.stream:
            if '$' in node:
                return True
            if char not in node:
                return False
            node = node[char]
        
        return '$' in node


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.memo = {}
        self.words = set()
        words_ = [word[::-1] for word in words]
        for word in words_:
            for i in range(len(word)-1):
                self.memo[word[:i+1]]=0
        
        for word in words_:
            self.memo[word]=1     
        
        self.hist = []
        
        #print(self.memo)
    
    def query(self, letter: str) -> bool:
        self.hist.append(letter)
        w = ''
        for i in range(len(self.hist)-1,-1,-1):
            w+=self.hist[i]
            #print(w)
            c = self.memo.get(w,None)
            if c is None:
                return False
            if c:
                return True
            
        return False



class Trie:
    def __init__(self):
        self.children = [None]*26
        self.end = False
    def insert(self,word):
        cur = self
        for letter in word:
            if cur.children[ord(letter)- ord('a')] == None:
                cur.children[ord(letter) - ord('a')] = Trie()
            cur = cur.children[ord(letter) - ord('a')]
        cur.end = True
        
    def search(self,s):
        cur = self
        for letter in s:
            if cur.children[ord(letter) - ord('a')] == None:
                return False
            cur = cur.children[ord(letter)-ord('a')]
            if cur.end == True:
                return True
        return False
class StreamChecker:
    from collections import deque
    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.words = words
        self.q = deque()
        for word in self.words:
            self.trie.insert(word[::-1])

    def query(self, letter: str) -> bool:
        self.q.appendleft(letter)
        return self.trie.search(self.q)
    

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    

    def __init__(self, words):
        self.words = []
        self.store = {}
        self.stack = ''
        self.sample = 15
        for w in words:
            if not w:
                continue
            self.insertStore(w[::-1], self.store)

    def query(self, letter):
        self.stack += letter
        return self.queryStore(self.stack, self.store)

    def insertStore(self, w, store):
        if w[:self.sample] not in store:
            store[w[:self.sample]] = {}
        if len(w) <= self.sample:
            store[w[:self.sample]]['!'] = None
        else:
            self.insertStore(w[self.sample:], store[w[:self.sample]])

    def queryStore(self, stack, store):
        if not stack:
            return False
        s = stack[:-self.sample-1:-1]
        if s in store:
            if '!' in store[s]:
                return True
            if self.queryStore(stack[:-self.sample], store[s]):
                return True
        for i in range(1, self.sample):
            if s[:i] in store:
                return True
        return False





class TrieNode():
    def __init__(self):
        self.children = {}
        self.isEnd = False


class Trie():
    def __init__(self):
        self.root = TrieNode()
    
    def insert(self, word):
        node = self.root
        
        for ch in word:
            if ch not in node.children:
                node.children[ch] = TrieNode()
            node = node.children[ch]
        
        node.isEnd = True


class StreamChecker:
    def __init__(self, words: List[str]):
        self.letters = []
        self.trie = Trie()
        
        for word in words:
            self.trie.insert(word[::-1])

    def query(self, letter: str) -> bool:
        self.letters.append(letter)
        i = len(self.letters)-1
        
        node = self.trie.root
        while i >= 0:
            if node.isEnd:
                return True
            if self.letters[i] not in node.children:
                return False
            node = node.children[self.letters[i]]
            i -= 1
        return node.isEnd
            
        

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter) 


class TrieNode:
    
    def __init__(self):
        self.child = {}
        self.isWord = False

class Tree:
    
    def __init__(self):
        self.root = TrieNode()
    
    def insert(self, word):
        cur = self.root
        for w in word:
            if w not in cur.child:
                cur.child[w] = TrieNode()
            cur = cur.child[w]
        cur.isWord = True

class StreamChecker:

    def __init__(self, words: List[str]):
        self.tree = Tree()
        for word in words:
            self.tree.insert(word[::-1])
        # self.printTree(self.tree.root)
        self.letter = []

    def query(self, letter: str) -> bool:
        self.letter.append(letter)
        cur = self.tree.root
        i = len(self.letter) - 1
        while i >= 0:
            if cur.isWord:
                return True
            if self.letter[i] not in cur.child:
                return False
            cur = cur.child[self.letter[i]]
            i -= 1
        return cur.isWord

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.children = {}
        self.isend_word = False

        
class Trie:
    def __init__(self):
        self.root = TrieNode()
    
    
    def insert(self, word):
        curr = self.root
        for c in word:
            if c not in curr.children:
                curr.children[c] = TrieNode()
            curr = curr.children[c]
        curr.isend_word = True
        
        
class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.search = []
        for word in words:
            self.trie.insert(word[::-1])
        
        
    def query(self, letter: str) -> bool: 
        self.search.append(letter)
        curr = self.trie.root
        i = len(self.search) - 1
        while i >= 0 and curr.children:
            char = self.search[i]
            if curr.isend_word:
                return True
            if char not in curr.children:
                return False
            curr = curr.children[char]
            i -= 1
        
        return curr.isend_word


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    def __init__(self):
        self.endOfWord = False
        self.children = [None]*26

    def insert(self, s):
        t = self
        for c in s:
            if t.children[ord(c)-ord('a')] == None:
                t.children[ord(c)-ord('a')] = Trie()
            t = t.children[ord(c)-ord('a')]
        t.endOfWord = True

    def search(self, s):
        t = self
        for c in s:
            if t.children[ord(c)-ord('a')] == None: return False
            t = t.children[ord(c)-ord('a')]
            if t.endOfWord: return True
        return False
    
class StreamChecker:

    def __init__(self, words: List[str]):
        self.t = Trie()
        self.stream = collections.deque()
        for w in words:
            self.t.insert(reversed(w))
            
        

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        return self.t.search(self.stream)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Node:
    
    def __init__(self):
        self.children = {}
        self.isEnd = False


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Node()
        for w in words:
            if(len(w) > 0):
                self.insert(w[::-1])
        self.queryStack = []
    
    def insert(self, word):
        root = self.trie
        self.insertWord(root, word, 0)
        
    
    def insertWord(self, curNode, word, index):
        if(index >= len(word)):
            curNode.isEnd = True
        else:
            curChar = word[index]
            if(curChar not in curNode.children):
                newNode = Node()
                curNode.children[curChar] = newNode
            self.insertWord(curNode.children[curChar], word, index+1)
    
    def findIfPresent(self, curNode, index):
        if(curNode.isEnd):
            return True
        if(index < 0):
            return False
        if(self.queryStack[index] not in curNode.children):
            return False
        return self.findIfPresent(curNode.children[self.queryStack[index]], index-1)
    
    def query(self, letter: str) -> bool:
        self.queryStack.append(letter)
        root = self.trie
        return self.findIfPresent(root, len(self.queryStack)-1)
        
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.children, self.end_node = {}, 0
         
class Trie:
    def __init__(self):
        self.root = TrieNode()

    def insert(self, word):
        root = self.root
        for symbol in word:
            root = root.children.setdefault(symbol, TrieNode())
        root.end_node = 1

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.Stream = deque()
        for word in words: 
            self.trie.insert(word[::-1])

    def query(self, letter: str) -> bool:
        self.Stream.appendleft(letter)
        cur = self.trie.root
        for c in self.Stream:
            if c in cur.children:
                cur = cur.children[c]
                if cur.end_node: 
                    return True
            else: 
                break
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


'''class StreamChecker:

    def __init__(self, words: List[str]):
        

    def query(self, letter: str) -> bool:
        


# Your StreamChecker object will be instantiated and calle as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)'''
class Trie:
    
    def __init__(self):
        self.endOfWord = False
        self.children = [None]*26

    def insert(self, s):
        t = self
        for c in s:
            if t.children[ord(c)-ord('a')] == None:
                t.children[ord(c)-ord('a')] = Trie()
            t = t.children[ord(c)-ord('a')]
        t.endOfWord = True

    def search(self, s):
        t = self
        for c in s:
            if t.children[ord(c)-ord('a')] == None: return False
            t = t.children[ord(c)-ord('a')]
            if t.endOfWord: return True
        return False


class StreamChecker:

    def __init__(self, words: List[str]):
        self.t = Trie()
        self.stream = collections.deque()
        for w in words:
            self.t.insert(reversed(w))

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        return self.t.search(self.stream)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = {}
        self.stream = collections.deque()
        for word in words:
            node = self.root
            for ch in word[::-1]:
                if ch not in node:
                    node[ch] = {}
                node = node[ch]
            node['#'] = {}
        
    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        node = self.root
        for ch in self.stream:
            if ch in node:
                node = node[ch]
                if '#' in node:
                    return True
            else:
                return False
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.arr = [None] * 26
        self.isWord = False

class StreamChecker:
    def __init__(self, words: List[str]):
        self.rt = TrieNode()
        self.S = \"\"
        self.mx = float('-inf')
        for w in words:
            node = self.rt
            for ch in w[::-1]:
                if node.arr[ord(ch) - ord('a')] is None:
                    node.arr[ord(ch) - ord('a')] = TrieNode()
                node = node.arr[ord(ch) - ord('a')]
            node.isWord = True
            self.mx = max(self.mx, len(w))

    def query(self, letter: str) -> bool:
        self.S = (letter + self.S)[:self.mx]
        node = self.rt
        for ch in self.S:
            if node.arr[ord(ch) - ord('a')] is None:
                return False
            node = node.arr[ord(ch) - ord('a')]
            if node.isWord:
                return True
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.curQuery = ''
        self.Trie = Trie()
        for word in words:
            newWord = word[::-1]
            self.Trie.insert(newWord)

    def query(self, letter: str) -> bool:
        self.curQuery = letter + self.curQuery
        curNode = self.Trie.root
        i = 0
        while curNode and i<len(self.curQuery):
            
            curLetter = self.curQuery[i]
            ind = ord(curLetter) - ord('a')
            curNode = curNode.children[ind]
            if not curNode:
                return False
            if curNode.isWord:
                return True
            
            i += 1
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Trie:
    def __init__(self):
        self.root = Node()
    def insert(self, word):
        curNode = self.root
        for i in range(len(word)):
            ind = ord(word[i])-ord('a')
            if curNode.children[ind]:
                curNode = curNode.children[ind]
            else:
                curNode.children[ind] = Node()
                curNode = curNode.children[ind]
        curNode.isWord = True
        return
                
        
class Node:
    def __init__(self):
        self.children = [None] * 26
        self.isWord = False

class TN:
    def __init__(self, eow=False):
        self.c = {}
        self.e = eow
        self.i = id(self)
    
    def add(self, s):
        if len(s)==0:
            self.e = True
        else:
            c = s[0]
            if c not in self.c:
                self.c[c] = TN()
            self.c[c].add(s[1:])
    
    def search(self, w):
        t = self
        for c in w:
            # print(c,t)
            if c not in t.c:
                # print('oops', t.c)
                return False
            else:
                t = t.c[c]
                if t.e:
                    return True
        # print('nope')
        return False
            
    
    def __contains__(self, i):
        return i in self.c
    
    def p(self, s=0):
        for k,v in self.c.items():
            print(' '*s, k, '*' if v.e else '', sep='')
            v.p(s+1)
    
    def __str__(self):
        return str(self.c)+('*'if self.e else '')
    def __repr__(self):
        return repr(self.c)+('*'if self.e else '')

class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = TN()
        for w in words:
            self.root.add(w[::-1])
        self.s = []
        # self.root.p()
        # self.av = set()

    def query(self, letter: str) -> bool:
        self.s.append(letter)
        return self.root.search(reversed(self.s))
        # found = False
        # print(self.av, letter)
        # for n in list(self.av):
        #     if letter in n:
        #         self.av.remove(n)
        #         self.av.add(n.c[letter])
        #         found = found or n.c[letter].e
        #     else:
        #         self.av.remove(n)
        # if letter in self.root:
        #     print('found',self.root.c[letter])
        #     self.av.add(self.root.c[letter])
        #     found = found or self.root.c[letter].e
        # print(found)
        # return found


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Trie:
    def __init__(self):
        self.child = {}

    def insert(self, word):
        cur = self
        for char in word + '$':
            if char not in cur.child:
                cur.child[char] = Trie()
            cur = cur.child[char]

    def search(self, word):
        cur = self
        for char in word + '$':
            if '$' in cur.child: return True
            if char in cur.child:
                cur = cur.child[char]
            else:
                return False
        return False
#
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        for word in words:
            word = word[::-1]
            self.trie.insert(word)
        self.buffer = ''
    

    def query(self, letter: str) -> bool:
        self.buffer=letter+ self.buffer
        return self.trie.search(self.buffer)

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.children = dict()
        self.isWord = False

class Trie:
    def __init__(self):
        self.root = TrieNode()
        
    def add(self, word):
        root = self.root
        for char in reversed(word):
            child = root.children.get(char, TrieNode())
            root.children[char] = child
            root = child
        root.isWord = True    
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.letters = []
        self.trie = Trie()
        for word in words:
            self.trie.add(word)
        
    def query(self, letter: str) -> bool:
        self.letters.append(letter)
        root = self.trie.root
        for char in reversed(self.letters):
            if char not in root.children:
                return False
            root = root.children[char]
            if root.isWord:
                return True

        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        Trie = lambda: collections.defaultdict(Trie)
        self.trie = Trie()
        for word in words:
            reduce(dict.__getitem__, word[::-1] + \"$\", self.trie)
        self.queries = \"\"

    def query(self, letter: str) -> bool:
        self.queries += letter
        curr = self.trie
        #print(\"query\")
        for i in range(len(self.queries)-1, -1, -1):
            c = self.queries[i]
            if \"$\" in curr:
                return True
            if c not in curr:
                return False
            curr = curr[c]
        return \"$\" in curr


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Node:
    def __init__(self):
        self.children = {}
        self.is_word = False

class StreamChecker:
    
    def __init__(self, words: List[str]):
        self.cache = Node()
        self.stream = []
        for word in words:
            root = self.cache
            for i in range(len(word) - 1, -1, -1):
                if word[i] in root.children:
                    root = root.children.get(word[i])
                else:
                    root.children[word[i]] = Node()
                    root = root.children.get(word[i])
            root.is_word = True

    def query(self, letter: str) -> bool:
        self.stream.append(letter)
        root = self.cache
        for i in range(len(self.stream) - 1, -1, -1):
            if self.stream[i] not in root.children:
                return False
            
            root = root.children.get(self.stream[i])
            if root.is_word:
                return True
            
        return False
        
        
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.children={}
        self.terminal=False

class Trie(object):

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

    def insert(self, word):
        \"\"\"
        Inserts a word into the trie.
        :type word: str
        :rtype: None
        \"\"\"
        if len(word) <= 0:
            return
        
        trav = self.root
        for i in range(len(word)):
            if word[i] in trav.children:
                trav = trav.children[word[i]]
            else:
                trav.children[word[i]] = TrieNode()
                trav = trav.children[word[i]]
        trav.terminal = True

class StreamChecker:
    # reference: https://leetcode.com/problems/stream-of-characters/discuss/320837/Easily-implemented-Python-Trie-Solution
    def __init__(self, words: List[str]):
        self.queries = []
        self.trie = Trie()
        for word in words:
            self.trie.insert(word[::-1])

    def query(self, letter: str) -> bool:
        # basically returns false if the letter is the oldest letter of the world
        # keep tracks of all queries from oldest to newest
        self.queries.append(letter)
        i = len(self.queries) - 1
        node = self.trie.root
        
        # iterate from the end so we are looking at the newest queries first
        # since word is saved backwords, it will return True
        while i >= 0:
            # already an end of a word
            if node.terminal:
                return True
            # there is no prefix of this
            if self.queries[i] not in node.children:
                return False
            node = node.children[self.queries[i]]
            i -= 1
        return node.terminal
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

from collections import deque
class Trie:
    def __init__(self, words):
        self.root = {}
        self.build(words)
    
    def build(self, words):
        for word in words:
            self.add_word(word[::-1])
            
    def add_word(self, word):
        node = self.root
        for ch in word:
            if ch not in node:
                node[ch] = {}
            node = node[ch]
        node[\"$\"] = True

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie(words)
        self.prev_letters = deque([])

    def query(self, letter: str) -> bool:
        self.prev_letters.appendleft(letter)
        node = self.trie.root
        for ch in self.prev_letters:
            if \"$\" in node:
                return True
            if ch in node:
                node = node[ch]
            else:
                return False
        
        return \"$\" in node

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)
\"\"\"
a, b, c, d

abcd, bcd, cd, d

\"\"\"

from collections import deque

class TrieNode(object):
    def __init__(self):
        self.children = {}
        self.nextFail = None
        self.suffixMatches = False

    def add(self, word, index=0):
        #print(word)
        if len(word) == index:
            self.boundary = True
            self.suffixMatches = True
            return
        c = word[index]
        if self.children.get(c, None) is None:
            self.children[c] = TrieNode()
        self.children[c].add(word, index + 1)
    def __str__(self):
        return self.__str2()

    def __str2(self, indent=0):
        space = \"  \"*indent
        return \"{}TrieNode(h={}, B={}, nf={},\
{}\".format(
            space,
            hash(self), self.suffixMatches, hash(self.nextFail) if self.nextFail else \"None\", \"\".join(space + k + \": \" + v.__str2(indent+1) + \"\
\" for k, v in self.children.items()),
            space
        ) + space + \")\"


class AhoTrie(object):
    def __init__(self, words):
        self.root = TrieNode()
        for word in words:
            self.root.add(word)
        self.__oho()

    def __oho(self):
        q = deque()
        for c, node in self.root.children.items():
            node.nextFail = self.root
            q.append(node)
        while len(q) > 0:
            node = q.popleft()
            
            for c, child in node.children.items():
                nextFail = node.nextFail
                while not nextFail.children.get(c) and nextFail is not self.root:
                    nextFail = nextFail.nextFail
                if not nextFail.children.get(c):
                    child.nextFail = nextFail
                else:
                    child.nextFail = nextFail.children.get(c)

                q.append(child)
                #child.nextFail = node.nextFail.children.get(c, node.nextFail)
                if  True: #child.suffixMatches:
                    nextFail = child.nextFail
                    while nextFail is not self.root and not nextFail.suffixMatches:
                        nextFail = nextFail.nextFail
                    if nextFail is not self.root:
                        child.suffixMatches = True





class StreamChecker:

    def __init__(self, words: List[str]):
        print(words)
        self.trie = AhoTrie(words) 
        self.root = self.trie.root
        self.cur = self.root
        #print(self.root)
        

    def query(self, letter: str) -> bool:
        
        
        while not self.cur.children.get(letter) and self.cur is not self.root:
            self.cur = self.cur.nextFail
        #print(hash(self.cur))
        if self.cur.children.get(letter):
            self.cur = self.cur.children[letter]
            temp = self.cur
            #while temp is not self.root:
            if temp.suffixMatches:
                return True
             #  temp = temp.nextFail
        return False
            
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

from collections import defaultdict
class Node:
    def __init__(self):
        self._childrn = defaultdict()
        self.wef = 0

class StreamChecker(Node):
    def __init__(self, words: List[str]):
        self.root = Node()
        self.wordh = \"\"
        
        for i in words:
            self.storeW(i)
            
    def _ind(self,ch):
        return(ord(ch) - ord('a'))

    def storeW(self,word):
        cur = self.root
        for i in word[::-1]:
            ind = self._ind(i)
            if ind not in cur._childrn:
                cur._childrn[ind] = Node()
            cur = cur._childrn[ind]
            
        cur.wef = True

    def query(self, letter: str) -> bool:
        cur = self.root
        self.wordh = letter + self.wordh
        for i in self.wordh:
            ind = self._ind(i)
            if not cur._childrn.get(ind):
                return(False)
            else:
                cur = cur._childrn.get(ind)
                if cur.wef:
                    return(True)
            
        
        return(False)
        



# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        for word in words:
            self.trie.insert(word[::-1])
        self.cache = ''

    def query(self, letter: str) -> bool:
        self.cache = letter + self.cache
        return self.trie.find(self.cache)
        
        
class TrieNode:
    def __init__(self):
        self.children = {}
        self.is_word = False

class Trie:
    def __init__(self):
        self.root = TrieNode()
    
    def insert(self, word):
        cur = self.root
        for c in word:
            cur.children.setdefault(c, TrieNode())
            cur = cur.children[c]
        cur.is_word = True
        
    def find(self, word):
        cur = self.root
        for c in word:    
            if cur.is_word:
                return True
            if c not in cur.children:
                return False
            cur = cur.children[c]
        return cur.is_word
        
        
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.dic = {}
        self.end = False
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = TrieNode()
        for word in words:
            word = \"\".join(reversed(word))
            self.addword(word)
        self.stream = \"\"
            
    def addword(self, word):
        current = self.root
        for char in word:
            if char not in current.dic:
                current.dic[char] = TrieNode()
            current = current.dic[char]
        current.end = True
            
    def helper(self, current, stream):
        for i in range(len(stream)):
            if stream[i] not in current.dic: 
                if current.end:
                    return True
                else:
                    return False
            else:
                if current.end:
                    return True
            current = current.dic[stream[i]]
        return current.end
        
    def query(self, letter: str) -> bool:
        self.stream = letter + self.stream
        return self.helper(self.root, self.stream)
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self):
        self.children = {}
        self.isEnd = False
        
class Trie:
    def __init__(self, corpus):
        self.root = TrieNode()
        for word in corpus:
            self.add(word)
        
    def add(self, word):
        x = self.root
        for w in word:
            if w not in x.children:
                x.children[w] = TrieNode()
            x = x.children[w]
        x.isEnd = True


class StreamChecker:

    def __init__(self, words: List[str]):
        words = [x[::-1] for x in words]
        self.trie = Trie(words)
        self.stream = deque()
        
    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        
        node = self.trie.root
        for w in self.stream:
            if node.isEnd:
                return True
            elif w not in node.children:
                return False
            else:
                node = node.children[w]
        return node.isEnd


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Node:
    def __init__(self, val=None):
        self.val = val
        self.children = {}
        self.isEnd = False
        

class StreamChecker:
    def add_word(self, word):
        word = word[::-1]
        i = 0
        curr = self.root
        while i < len(word):
            if word[i] in curr.children:
                curr = curr.children[word[i]]
                if i == len(word)-1:
                    curr.isEnd = True
                i += 1
            else:
                break
        while i < len(word):
            curr.children[word[i]] = Node(word[i])
            curr = curr.children[word[i]]
            if i == len(word)-1:
                curr.isEnd = True
            i += 1

    def __init__(self, words: List[str]):
        self.root = Node()
        self.stream = \"\"
        for w in words:
            self.add_word(w)

    def query(self, letter: str) -> bool:
        self.stream  = letter + self.stream
        i = 0
        curr = self.root
        while i < len(self.stream):
            if self.stream[i] in curr.children:
                curr = curr.children[self.stream[i]]
                if curr.isEnd:
                    return True
            else:
                return False
            i += 1
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    
    def __init__(self):
        self.children = {}
        self.end_node = 0

class Trie:
    def __init__(self):
        self.root = TrieNode()
    
    def insert(self, word: str):
        root = self.root
        for w in word:
            root = root.children.setdefault(w, TrieNode())
        root.end_node = 1
        
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.t = Trie()
        self.stream = deque()
        for w in words:
            self.t.insert(w[::-1])

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        t = self.t.root
        for curr in self.stream:
            if curr in t.children:
                t = t.children[curr]
                if t.end_node:
                    return True
            else:
                break
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class node :
    
    def __init__(self) :
        self.child = [None]*26
        self.end = False
        
    def insert(self , word) :
        cur = self
        
        for i in range(len(word)) :
            index = self.indexof(word[i])
            
            if cur.child[index] == None :
                cur.child[index] = node()
            
            cur = cur.child[index] 
            
        cur.end = True
        
    def search(self , word) :
        
        cur = self
        
        for w in word :
            index = self.indexof(w) 
            
            cur = cur.child[index] 
            
            if cur != None :
                if cur.end == True :
                    return True
            
            else :
                break 
                
        return False
    
    def indexof(self , c) :
        return ord(c) - ord('a')
    
class StreamChecker:

    def __init__(self, words: List[str]):
        self.words = words
        self.root = node()
        self.stack = collections.deque()
        
        for w in words :
            self.root.insert(w[::-1])
            
    def query(self, letter: str) -> bool:
        self.stack.appendleft(letter)
        
        return self.root.search(self.stack)
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import defaultdict
from functools import reduce

class StreamChecker:

    def __init__(self, words: List[str]):
        # O(N x M)

        # self.s = \"\"
        # self.dic = defaultdict(set)
        # for w in words:
        #     self.dic[w[-1]].add(w)

        # Trie = lambda: defaultdict(Trie)
        # self.trie = Trie()
        # for word in words:
        #     reduce(dict.__getitem__, word, self.trie)['#'] = True
        # self.waiting = []


        Trie = lambda: defaultdict(Trie)
        self.trie = Trie()
        for word in words:
            reduce(dict.__getitem__, word[::-1], self.trie)['#'] = True
        self.S = \"\"
        self.W = max(map(len, words))

        

    def query(self, letter: str) -> bool:
        # O(M) where M is a max word length.

        # self.s += letter
        # return any(self.s.endswith(w) for w in self.dic[letter])

        # self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        # return any('#' in node for node in self.waiting)

        self.S = (letter + self.S)[:self.W]
        cur = self.trie
        for c in self.S:
            if c in cur:
                cur = cur[c]
                if cur['#']:
                    return True
            else:
                break
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

from collections import deque, defaultdict as dd

class TrieNode:
    def __init__(self):
        self.children = dd(TrieNode)
        self.is_end = False
        
class StreamChecker:
    def __init__(self, words: List[str]):
        self.q = deque()
        self.root = TrieNode()
        
        for word in words:
            node = self.root
            for char in word[::-1]:
                node = node.children[char]
            node.is_end = True

    def query(self, letter: str) -> bool:
        self.q.appendleft(letter)
        node = self.root
        
        for char in self.q:
            if char not in node.children:
                break
            node = node.children[char]
            if node.is_end:
                return True
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.memo = [{} for i in range(2000)]
        self.words = set()
        words_ = [word[::-1] for word in set(words)]
        for word in words_:
            for i in range(len(word)-1):
                self.memo[i+1][word[:i+1]]=0
        
        for word in words_:
            self.memo[len(word)][word]=1     
        
        self.hist = []
        
        #print(self.memo)
    
    def query(self, letter: str) -> bool:
        self.hist.append(letter)
        w = ''
        for i in range(len(self.hist)-1,-1,-1):
            w+=self.hist[i]
            #print(w)
            c = self.memo[len(w)].get(w,None)
            if c is None:
                return False
            if c:
                return True
            
        return False


class StreamChecker:
    def __init__(self, words: List[str]):
        self.words = words
        self.cur = ''
        self.trie = {}

        for word in words:
            word = word[::-1]

            tmp = self.trie
            for w in word:
                if w not in tmp:
                    tmp[w] = dict()
                    tmp = tmp[w]
                else:
                    tmp = tmp[w]

            tmp['#'] = None

    def query(self, letter: str) -> bool:
        self.cur += letter

        point = self.trie
        for i in range(len(self.cur) - 1, -1, -1):
            t = self.cur[i]

            if '#' in point:
                return True

            if t not in point:
                return False

            point = point[t]
 
        if '#' in point:
            return True
        else:
            return False


from collections import deque
class TrieNode:
    def __init__(self):
        self.children = {}
        self.isEndWord = False

class Trie:
    def __init__(self):
        self.root = TrieNode()

    def addWord(self, word):
        head = self.root
        for char in word:
            head = head.children.setdefault(char, TrieNode())
        head.isEndWord = True


class StreamChecker:
    def __init__(self, words):
        self.vocab = Trie()
        self.queue = deque()
        for word in words:
            self.vocab.addWord(word[::-1])

    def query(self, char):
        self.queue.appendleft(char)
        cur = self.vocab.root
        for c in self.queue:
            if c in cur.children:
                cur = cur.children[c]
                if cur.isEndWord:
                    return True
            else:
                break
        return False

from collections import deque
class Node:
    def __init__(self, char):
        self.char = char
        self.children = {}
        self.word = \"\"

class Trie:
    def __init__(self):
        self.root = Node(\"\")

    def add_word(self, word):
        def helper(next_idx, node):
            next_char = word[next_idx]
            if next_char not in node.children:
                node.children[next_char] = Node(next_char)
            node = node.children[next_char]
            if next_idx == len(word) - 1:
                node.word = word
            else:
                helper(next_idx+1, node)
        helper(0, self.root)

    def word_exists(self, word):
        def helper(next_idx, node):
            if node.word:
                return True
            if next_idx >= len(word):
                return False
                
            next_char = word[next_idx]
            if next_char not in node.children:
                return False
            node = node.children[next_char]
            return helper(next_idx+1, node)
            
        return helper(0, self.root)
        

class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.max_word_length = 0
        for word in words:
            self.trie.add_word(word[::-1])
            self.max_word_length = max(self.max_word_length, len(word))
        self.q = deque()

    def query(self, letter: str) -> bool:
        if len(self.q) == self.max_word_length:
            self.q.pop()
        self.q.appendleft(letter)
        return self.trie.word_exists(self.q)
    # [\"cde\"]
    # [\"c\" Node<d>, \"d\" None] e
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self):
        self.child = [None]*26
        self.is_leaf = False

class StreamChecker:

    def __init__(self, words: List[str]):
        root = TrieNode()
        for word in words:
            l = len(word)
            node = root
            for i in range(l-1,-1,-1):
                index = ord(word[i]) - 97
                if node.child[index] is None:
                    node.child[index] = TrieNode()
                node = node.child[index]
            node.is_leaf = True
        self.root = root
        self.queue = []
        
    def query(self, letter: str) -> bool:
        self.queue.append(letter)
        if len(self.queue) > 2000:
            self.queue.pop(0)
        index = len(self.queue) - 1
        node = self.root
        while index >=0:
            current = ord(self.queue[index]) - 97
            node = node.child[current]
            if node is None:
                return False
            elif node.is_leaf:
                return True
            index -= 1
        return False
                
            
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import deque

class TrieNode(object):
    def __init__(self):
        self.children = {}
        self.nextFail = None
        self.suffixMatches = []

    def add(self, word, index=0):
        #print(word)
        if len(word) == index:
            self.boundary = True
            self.suffixMatches = [word]
            return
        c = word[index]
        if self.children.get(c, None) is None:
            self.children[c] = TrieNode()
        self.children[c].add(word, index + 1)
    def __str__(self):
        return self.__str2()

    def __str2(self, indent=0):
        space = \"  \"*indent
        return \"{}TrieNode(h={}, B={}, nf={},\
{}\".format(
            space,
            hash(self), self.suffixMatches, hash(self.nextFail) if self.nextFail else \"None\", \"\".join(space + k + \": \" + v.__str2(indent+1) + \"\
\" for k, v in self.children.items()),
            space
        ) + space + \")\"


class AhoTrie(object):
    def __init__(self, words):
        self.root = TrieNode()
        for word in words:
            self.root.add(word)
        self.__oho()

    def __oho(self):
        q = deque()
        for c, node in self.root.children.items():
            node.nextFail = self.root
            q.append(node)
        while len(q) > 0:
            node = q.popleft()
            
            for c, child in node.children.items():
                nextFail = node.nextFail
                while not nextFail.children.get(c) and nextFail is not self.root:
                    nextFail = nextFail.nextFail
                if not nextFail.children.get(c):
                    child.nextFail = nextFail
                else:
                    child.nextFail = nextFail.children.get(c)

                q.append(child)
                #child.nextFail = node.nextFail.children.get(c, node.nextFail)
                if  True: #child.suffixMatches:
                    nextFail = child.nextFail
                    while nextFail is not self.root and not nextFail.suffixMatches:
                        nextFail = nextFail.nextFail
                    if nextFail is not self.root:
                        child.suffixMatches.extend(nextFail.suffixMatches)





class StreamChecker:

    def __init__(self, words: List[str]):
        print(words)
        self.trie = AhoTrie(words) 
        self.root = self.trie.root
        self.cur = self.root
        #print(self.root)
        

    def query(self, letter: str) -> bool:
        
        
        while not self.cur.children.get(letter) and self.cur is not self.root:
            self.cur = self.cur.nextFail
        #print(hash(self.cur))
        if self.cur.children.get(letter):
            self.cur = self.cur.children[letter]
            temp = self.cur
            #while temp is not self.root:
            if temp.suffixMatches:
                return True
             #  temp = temp.nextFail
        return False
            
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            level = self.trie
            for char in reversed(word):
                if char not in level:
                    level.update({char:{}})
                level = level[char]
            level.update({'.':{}})
            
        self.stream = ''

    def query(self, letter: str) -> bool:
        self.stream += letter
        level = self.trie
        for char in reversed(self.stream):
            if '.' in level:
                return True
            if char not in level:
                return False
            level = level[char]
        if '.' in level:
            return True
        return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = {}
        self.stream = deque([])
        for word in words:
            node = self.root
            for ch in word[::-1]:
                node.setdefault(ch, {})
                node = node[ch]
            node['#'] = {}

        
    def query(self, letter: str) -> bool:
        self.stream.append(letter)
        node = self.root
        for i in range(len(self.stream) -1, -1, -1):
            if self.stream[i] not in node:
                return False
            node = node[self.stream[i]]
            if \"#\" in node:
                return True
        return \"#\" in node
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TreeNode:
    def __init__(self):
        self.children = {}
        self.value = None
    def insert(self, string):
        root = self
        for char in string:
            if char not in root.children:
                root.children[char] = TreeNode()
            root = root.children[char]
        root.value = string
    def find(self, string):
        root = self
        for char in string:
            if char in root.children:
                root = root.children[char]
            else:
                return None
        return root.value
                 
class StreamChecker:
    def __init__(self, words):
        self.root = TreeNode()
        self.characters = deque()
        for word in words:
            self.root.insert(word[::-1])
    def query(self, letter: str) -> bool:
        self.characters.appendleft(letter)
        node = self.root
        for char in self.characters:
            if char in node.children:
                node = node.children[char]
                if node.value:
                    return True
            else:
                return False



class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.stream = deque([])

        for word in set(words):
            node = self.trie       
            for ch in word[::-1]:
                if not ch in node:
                    node[ch] = {}
                node = node[ch]
            node['$'] = word
        
        
    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        
        node = self.trie
        for ch in self.stream:
            if '$' in node:
                return True
            if not ch in node:
                return False
            node = node[ch]
        return '$' in node
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    def __init__(self):
        self.root = {}
    
    def create_Trie(self,word):
        cur_node = self.root
        for w in word:
            if w not in cur_node:
                cur_node[w] = {}
            cur_node = cur_node[w]
        cur_node[\"$\"] = word
        
        



class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        for word in words:
            self.trie.create_Trie(word[::-1])
        self.stream = collections.deque()
        

    def query(self, letter: str) -> bool:
        
        self.stream.appendleft(letter)
        cur_node = self.trie.root
        for char in self.stream:
            if \"$\" in cur_node:
                return True
            if char not in cur_node:
                return False
            cur_node = cur_node[char]
        return \"$\" in cur_node
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:
    class Trie:
        def __init__(self):
            self.next = {}
            self.ending = False
            
        def add(self,s):
            if s != \"\":
                if s[0] not in self.next:
                    self.next[s[0]] = StreamChecker.Trie()
                self.next[s[0]].add(s[1:])
            else:
                self.ending = True
                
        def __contains__(self,s):
            if self.ending:
                return True
            elif s == \"\":
                return False
            elif s[-1] in self.next:
                return self.next[s[-1]].__contains__(s[:len(s)-1])
            else:
                return False
            
    def __init__(self, words: List[str]):
        self.words = self.Trie()
        for w in words: self.words.add(w[::-1])
        self.maxSize = max(len(w) for w in words)
        self.q = \"\"

    def query(self, letter: str) -> bool:
        self.q += letter
        if len(self.q) > self.maxSize: self.q = self.q[1:]
        return self.q in self.words

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self):
        self.is_word = False
        self.children = {}

class Trie:
    
    def __init__(self):
        self.root = TrieNode()
    
    def add_word(self, word):
        node = self.root
        for c in word:
            if c not in node.children:
                node.children[c] = TrieNode()
            node = node.children[c]
        node.is_word = True
    
    def search_word(self, word):
        node = self.root
        for c in word:
            if c not in node.children:
                return False
            if node.children[c].is_word:
                return True
            node = node.children[c]
        return False


class StreamChecker:

    def __init__(self, words: List[str]):
        self.input = deque()
        self.trie = Trie()
        self.max_len = 0
        for word in words:
            self.trie.add_word(word[::-1])
            self.max_len = max(self.max_len, len(word))

    def query(self, letter: str) -> bool:
        self.input.appendleft(letter)
        if len(self.input) > self.max_len:
            self.input.pop()
        return self.trie.search_word(self.input)

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    
    def __init__(self):
        self.endOfWord = False
        self.children = [None]*26

    def insert(self, s):
        t = self
        for c in s:
            if t.children[ord(c)-ord('a')] == None:
                t.children[ord(c)-ord('a')] = Trie()
            t = t.children[ord(c)-ord('a')]
        t.endOfWord = True

    def search(self, s):
        t = self
        for c in s:
            if t.children[ord(c)-ord('a')] == None: return False
            t = t.children[ord(c)-ord('a')]
            if t.endOfWord: return True
        return False


class StreamChecker:

    def __init__(self, words: List[str]):
        self.t = Trie()
        self.stream = collections.deque()
        for w in words:
            self.t.insert(reversed(w))

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        return self.t.search(self.stream)

class TrieNode:
    def __init__(self):
        self.children, self.end_node = {}, 0
         
class Trie:
    def __init__(self):
        self.root = TrieNode()

    def insert(self, word):
        root = self.root
        for symbol in word:
            root = root.children.setdefault(symbol, TrieNode())
        root.end_node = 1

class StreamChecker:
    def __init__(self, words):
        self.trie = Trie()
        self.Stream = deque()
        for word in words: self.trie.insert(word[::-1])
         
    def query(self, letter):
        self.Stream.appendleft(letter)
        cur = self.trie.root
        for c in self.Stream:
            if c in cur.children:
                cur = cur.children[c]
                if cur.end_node: return True
            else: break
        return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.children = dict()
        self.end = False

class Trie:
    def __init__(self):
        self.root = TrieNode()

    def insert(self, word):
        root = self.root
        for c in word:
            root  = root.children.setdefault(c, TrieNode())
        root.end = True

    def search(self, word):
        root = self.root
        for c in word:
            if c not in root.children:
                return False
            root = root.children[c]
            if root.end:
                return True
        return False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.curr = \"\"
        for word in words:
            self.trie.insert(reversed(word))

    def query(self, letter: str) -> bool:
        self.curr+=letter
        if self.trie.search(reversed(self.curr)):
            return True
        return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:
    
    history = None

    def __init__(self, words: List[str]):
        self.history = \"\"
        self.index = {}
        for w in words:
            idx = self.index.get(w[-1], [])
            idx.append(w)
            self.index[w[-1]] = idx
        
    def query(self, letter: str) -> bool:
        self.history = self.history + letter
        for word in self.index.get(letter, []):
            if self.history.endswith(word):
                return True
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    
    def __init__(self):
        self.children = {}
        self.is_word = False
        
    def add_child(self, c):
        return self.children.setdefault(c, TrieNode())
    
    def get_child(self, c):
        return self.children.get(c)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.data = []
        self.root = TrieNode()
        for word in words:
            node = self.root
            for c in reversed(word):
                node = node.add_child(c)
            node.is_word = True

    def query(self, letter: str) -> bool:
        self.data.append(letter)
        node = self.root
        for i in range(len(self.data) - 1, -1, -1):
            node = node.get_child(self.data[i])
            if node is not None and node.is_word:
                return True
            elif node is None:
                return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.neighbor = {}  # char -> TrieNode
        self.isend = False
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie_root = TrieNode()
        self.letters = []
        self.max_len = max(list(map(len, words)))
        
        for word in words:
            curr = self.trie_root
            for c in word[::-1]:
                if c not in curr.neighbor:
                    curr.neighbor[c] = TrieNode()
                curr = curr.neighbor[c]
            curr.isend = True
        
    def query(self, letter: str) -> bool:
        self.letters.append(letter)
        self.letters = self.letters[max(0, len(self.letters) - self.max_len):]
     
        curr = self.trie_root
        for l in self.letters[::-1]:
            if l in curr.neighbor:
                curr = curr.neighbor[l]
                if curr.isend:
                    return True
            else:
                return False
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.children = [None]*26
        self.isWord = False
        
class Trie:
    def __init__(self):
        self.root = TrieNode()
        
    def addWord(self, word):
        curr = self.root
        for letter in word:
            index = ord(letter) - ord('a')
            if not curr.children[index]:
                curr.children[index] = TrieNode()
            curr = curr.children[index]
        curr.isWord = True
        
    def search(self, word):
        curr = self.root
        for letter in word:
            index = ord(letter) - ord('a')
            if not curr.children[index]: 
                return False
            curr = curr.children[index]
            if curr.isWord: return True
        return False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.maxLength = 0
        self.q = []
        self.size = 0
        for word in words:
            revWord = word[::-1]
            length = len(revWord)
            self.maxLength = max(self.maxLength, length)
            self.trie.addWord(revWord)
        

    def query(self, letter: str) -> bool:
        self.q.append(letter)
        self.size += 1
        if self.size > self.maxLength:
            self.q.pop(0)
            self.size -= 1
        return self.trie.search(self.q[::-1])
            
        
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Node:
    def __init__(self):
        self.kids = collections.defaultdict(Node)
        self.end = False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = Node()
        self.s = \"\"
        for word in words:
            t = self.root
            for w in word[::-1]:
                t = t.kids[w]
            t.end = True

    def query(self, letter: str) -> bool:
        self.s += letter
        if len(self.s) > 2000:
            self.s = self.s[-2000:]
        def dfs(t, word):
            for w in word:
                if w not in t.kids:
                    return False
                t = t.kids[w]
                if t.end:
                    return True
            return False
        return dfs(self.root, self.s[::-1])


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Trie:
    def __init__(self):
        self.trie = {}
    def insert(self,w):
        t = self.trie
        for c in w+'\\0':
            if c not in t: t[c] = {}
            t = t[c]
    def match(self,w):
        t = self.trie
        for c in w:
            if c not in t: return False
            t = t[c]
            if '\\0' in t: return True


class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie = Trie()
        for word in words:
            self.trie.insert(word[::-1])
        self.stream = deque()
            
    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        return self.trie.match(self.stream)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TreeNode:
    def __init__(self):
        self.children = {}
        self.value = None
    def insert(self, string):
        root = self
        for char in string:
            if char not in root.children:
                root.children[char] = TreeNode()
            root = root.children[char]
        root.value = string
    def find(self, string):
        root = self
        for char in string:
            if char in root.children:
                root = root.children[char]
            else:
                return None
        return root.value
                 
class StreamChecker:
    def __init__(self, words):
        self.root = TreeNode()
        self.characters = \"\"
        for word in words:
            self.root.insert(word[::-1])
    def query(self, letter: str) -> bool:
        self.characters = letter + self.characters
        node = self.root
        for char in self.characters:
            if char in node.children:
                node = node.children[char]
                if node.value:
                    return True
            else:
                return False



class StreamChecker:
    from collections import deque
    def __init__(self, words: List[str]):
        self.trie = dict()
        maxlen = 0
        #d = self.trie 
        for word in words:
            maxlen = max(maxlen,len(words))
            d = self.trie
            for i in range(len(word)-1, -1, -1):
                if word[i] not in d:
                    d[word[i]] = dict()
                d = d[word[i]]
            d[\"#\"]=dict()
        self.maxlen = maxlen
        #print(self.trie)
        self.history = deque([])
        

    def query(self, letter: str) -> bool:
        self.history.appendleft(letter)
        if len(self.history)>self.maxlen:
            self.history.pop()
        d = self.trie
        #print(self.history)
        for l in range(len(self.history)):
            #print(letter,self.history[l])
            if self.history[l] in d:
                d = d[self.history[l]]
                if \"#\" in d:
                    return True
            else:
                return False
                
                
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Node:
    def __init__(self):
        self.m = {}
        self.end = False
    
    def get(self, c):
        return self.m.get(c)
    
    def put(self, c, node):
        self.m[c] = node
        

class Trie:
    def __init__(self):
        self.root = Node()
    
    def insert(self, word):
        node = self.root
        for c in word[::-1]:
            if not node.get(c):
                node.put(c, Node())
            node = node.get(c)
        node.end = True
    
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.stream = deque([])
        for word in words:
            self.trie.insert(word)

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        node = self.trie.root
        ans = ''
        for c in self.stream:
            if node.end:
                return True
            if not node.get(c):
                return False
            node = node.get(c)
        return node.end
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:    
    def __init__(self):
        self.children = {}
        self.is_leaf = False
    
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = TrieNode()
        self.root = self.trie
        self.buf = []
        
        for word in words:
            self.trie = self.root
            for i in range(len(word)-1, -1, -1):
                ch = word[i]
                if ch not in self.trie.children:
                    self.trie.children[ch] = TrieNode()
                self.trie = self.trie.children[ch]
            self.trie.is_leaf = True
        

    def query(self, letter: str) -> bool:
        self.buf.append(letter)
        self.trie = self.root
        for i in range(len(self.buf)-1,-1,-1):            
            if self.buf[i] in self.trie.children:
                self.trie = self.trie.children[self.buf[i]]
                if self.trie and self.trie.is_leaf:
                    return True
            else:
                return False

        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.children = {}
        self.isend_word = False

        
class Trie:
    def __init__(self):
        self.root = TrieNode()
    
    
    def insert(self, word):
        curr = self.root
        for c in word:
            if c not in curr.children:
                curr.children[c] = TrieNode()
            curr = curr.children[c]
        curr.isend_word = True
        
        
class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.search = []
        for word in words:
            self.trie.insert(word[::-1])
        
        
    def query(self, letter: str) -> bool: 
        self.search.append(letter)
        curr = self.trie.root
        for i in reversed(list(range(len(self.search)))):
            char = self.search[i]
            if curr.isend_word:
                return True
            if char not in curr.children:
                return False
            curr = curr.children[char]
        
        return curr.isend_word


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Node:
    def __init__(self,):
        self.children=[None]*26
        self.terminal=False

class Trie:
    def __init__(self,):
        self.root=Node()
        self.size=0
        
    def get_index(self,x):
        return ord(x)-ord('a')
        
    def insert(self,input_str):
        curr=self.root
        for x in input_str:
            c=self.get_index(x)
            if curr.children[c] is not None:
                curr=curr.children[c]
            else:
                curr.children[c]=Node()
                curr= curr.children[c]
        curr.terminal=True
        
        
    def search(self,input_str):
        curr=self.root
        for x in input_str:
            c=self.get_index(x)
            if curr.children[c] is not None:
                curr=curr.children[c]
                if curr.terminal:
                    return True
            else:
                return False
        return curr.terminal


class StreamChecker:
    def __init__(self, words: List[str]):        
        self.trie=Trie()
        for word in words:
            self.trie.insert(word[::-1])
        self.request_string=''  
        
    def query(self, letter: str) -> bool:
        '''
        ab ba aaab abab baa
        
        ba ab 
        
        '''
        self.request_string=letter+self.request_string
        result=self.trie.search(self.request_string)
        
        return result
            
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    def __init__(self):
        self.head = {}

    def insert(self, word):
        cur = self.head
        for ch in word:
            if ch not in cur:
                cur[ch] = {}
            cur = cur[ch]
        cur['*'] = True

    def search(self, word):
        cur = self.head
        for ch in word:
            if ch not in cur:
                return False
            cur = cur[ch]
        if cur.get('*'):
            return True
        return False
    
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.max_len = 0
        words = list([s[::-1] for s in words])
        for word in words:
            self.max_len = max(self.max_len, len(word))
            self.trie.insert(word)
        self.query_store = deque(maxlen=self.max_len)
        

    def query(self, letter: str) -> bool:
        self.query_store.appendleft(letter)
        query = ''.join(self.query_store)
        cur = self.trie.head
        for ch in query:
            if ch not in cur:
                return False
            cur = cur[ch]
            if cur.get('*'):
                return True
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.children = {}
        self.is_word = False
        
class Trie:
    def __init__(self):
        self.root = TrieNode()
    
    def insert(self, word):
        node = self.root
        for ch in word:
            if ch not in node.children:
                node.children[ch] = TrieNode()
            node = node.children[ch]
        node.is_word = True
    
    def find(self, word):
        node = self.root
        for ch in word:
            if ch not in node.children:
                return False
            node = node.children[ch]
            if node.is_word:
                return True
        return False
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.history = \"\"
        for word in words:
            self.trie.insert(word[::-1])
        

    def query(self, letter: str) -> bool:
        self.history = letter + self.history
        return self.trie.find(self.history)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self):
        self.children = {}
        self.is_word = False

class Trie:
    def __init__(self):
        self.root = TrieNode()
    
    def add_word(self, word: str) -> None:
        node = self.root
        for ch in word:
            if ch not in node.children:
                node.children[ch] = TrieNode()
            node = node.children[ch]
        node.is_word = True


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.stream = collections.deque()
        self.size = 0
        
        for word in words:
            self.size = max(len(word), self.size)
            self.trie.add_word(word[::-1])
        

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        
        # stream is limited to length of longest word
        if len(self.stream) > self.size:
            self.stream.pop()
        
        node = self.trie.root
        for ch in self.stream:
            if node.is_word:
                return True
            if ch not in node.children:
                return False
            node = node.children[ch]
        return node.is_word


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = {}
        self.stream = collections.deque()
        for word in words:
            node = self.root
            for ch in word[::-1]:
                if ch not in node:
                    node[ch] = {}
                node = node[ch]
            node['#'] = {}
        # print(self.root)
        
    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        node = self.root
        # print('=>', letter)
        for ch in self.stream:
            if ch in node:
                # print(ch)
                node = node[ch]
                if '#' in node:
                    return True
            else:
                return False
        return '#' in node
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.memo = {}
        self.words = set()
        for word in words:
            word_ = word[::-1]
            for i in range(len(word)):
                self.memo[word_[:i+1]]=0
            self.words.add(word_)        
        self.hist = []
        
        #print(self.memo)
    
    def query(self, letter: str) -> bool:
        self.hist.append(letter)
        w = ''
        for i in range(len(self.hist)-1,-1,-1):
            w+=self.hist[i]
            #print(w)
            if w not in self.memo:
                return False
            if w in self.words:
                return True
        return False



class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = self._get_trie(words)
        self.stream = collections.deque()
    
    def _get_trie(self, words):
        trie = ({}, False)
        
        for w in words:
            cur = trie
            n = len(w)
            for i, c in enumerate(w[::-1]): 
                \"\"\"
                reversing the word is crucial for runtime
                \"\"\" 
                is_last_letter = i == n - 1
                
                if c not in cur[0]:
                    cur[0][c] = ({}, is_last_letter)
                elif c in cur[0] and not cur[0][c][1] and is_last_letter:
                    cur[0][c] = (cur[0][c][0], is_last_letter)
                
                cur = cur[0][c]
            
        return trie
    
#     def _search(self, word):
#         cur = self.trie
#         for c in word:
#             if c in cur[0]:
#                 cur = cur[0][c]
#             else:
#                 return (False, False)
        
#         return (cur[1], True)

    
    def _search_any(self, word):
        cur = self.trie
        for c in word:
            if c in cur[0]:
                cur = cur[0][c]
            else:
                return False
            
            if cur[1]:
                return True
        
        return False

#     def query_2(self, letter: str) -> bool:
#         self.stream.append(letter)
#         word = copy.copy(self.stream)
#         word_seen = False
#         for i in range(len(self.stream)):
#             search = self._search(word)
#             if search[0]:
#                 return True
#             if not search[1] and not word_seen:
#                 self.stream.popleft()
#             else:
#                 word_seen = True
#             word.popleft()
        
#         return False
    
    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        return self._search_any(self.stream)



# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self):
        self.child = {}
        self.isword = False
class Trie:
    def __init__(self):
        self.root = TrieNode()
    
    def insert(self, word):
        node = self.root
        for w in word:
            if w not in node.child:
                node.child[w] = TrieNode()
            node = node.child[w]
        node.isword = True
        
    def search(self, word):
        node = self.root
        for w in word:
            if w in node.child:
                if node.child[w].isword == True: return True
                node = node.child[w]
            else: return False
        return False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        for word in words:
            self.trie.insert(word[::-1])
        self.stack = []
        self.size = max(len(word) for word in words)
    def query(self, letter: str) -> bool:
        if len(self.stack) >= self.size:
            self.stack.pop(0)
        self.stack.append(letter)
        return self.trie.search(''.join(self.stack[::-1]))


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self, val):
        self.val = val
        self.links = {}
        self.is_end = False
    
    def getLink(self, char):
        return self.links.get(char)
    
    def addLink(self, node):
        self.links[node.val] = node
    
    def setEnd(self):
        self.is_end = True

class Trie:
    def __init__(self):
        self.roots = [None] * 26
    
    def insertWord(self, word):
        if self.roots[ord(word[0]) - ord('a')] is None:
            self.roots[ord(word[0]) - ord('a')] = TrieNode(word[0])
        
        currNode = self.roots[ord(word[0]) - ord('a')]
        
        for i in range(1, len(word)):
            char = word[i]
            nextNode = currNode.getLink(char)
            if nextNode is None:
                nextNode = TrieNode(char)
                currNode.addLink(nextNode)
            currNode = nextNode
        
        currNode.setEnd()

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        maxLen = 0
        for word in words:
            self.trie.insertWord(word[::-1])
            maxLen = max(maxLen, len(word))
        
        self.maxsize = maxLen
        self.stream = []
        self.streamsize = 0

    def query(self, letter: str) -> bool:
        if self.streamsize == self.maxsize:
            self.stream = self.stream[1:]
            self.streamsize -= 1
        
        self.stream.append(letter)
        self.streamsize += 1
        
        node = None
        
        for i in range(len(self.stream) -1, -1, -1):
            rootChar = self.stream[i]
            if node is None:
                node = self.trie.roots[ord(rootChar) - ord('a')]
            else:
                nextNode = node.getLink(rootChar)
                node = nextNode
            if node is None:
                break
            elif node.is_end:
                return True

        return False
        
        

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            word = word[::-1]
            cur = self.trie
            for char in word:
                if char not in cur:
                    cur[char] = {}
                cur = cur[char]
            cur['$'] = {}
        self.queries = []

    def query(self, letter: str) -> bool:
        self.queries.insert(0, letter)
        cur = self.trie
        for char in self.queries:
            if '$' in cur:
                return True
            if char not in cur:
                return False
            cur = cur[char]
        return ('$' in cur)

    def __repr__(self):
        return \"Trie: \" + str(self.trie) + \"\
\" + \"Queries: \" + str(self.queries)





# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self):
        self.children = {}
        self.isEnd = False
        
class Trie:
    def __init__(self):
        self.root = TrieNode()
    
    def insert(self, word):
        curr = self.root
        for ch in word:
            if ch not in curr.children:
                curr.children[ch] = TrieNode()
            curr = curr.children[ch]
        curr.isEnd = True
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.letters = []
        self.trie = Trie()
        for word in words:
            self.trie.insert(word[::-1])

    def query(self, letter: str) -> bool:
        self.letters.append(letter)
        i = len(self.letters) - 1
        curr = self.trie.root
        while i >= 0:
            if curr.isEnd == True:
                return True
            if self.letters[i] not in curr.children:
                return False
            curr = curr.children[self.letters[i]]
            i -= 1
        return curr.isEnd


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
    def __init__(self, words: List[str]):
        self.Trie = {}
        for word in words:
            curnode=self.Trie
            word = word[::-1]
            for ch in word:
                if ch not in curnode:
                    curnode[ch]={}
                curnode=curnode[ch]
            curnode['#']=1
        self.pre=''

    def query(self, letter: str) -> bool:
        self.pre=self.pre+letter
        curnode=self.Trie
        for i in range(0, len(self.pre)):
            if self.pre[-i-1] not in curnode:
                break
            curnode=curnode[self.pre[-i-1]]
            if '#' in curnode:
                return True
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import deque
class Node:
    def __init__(self, char):
        self.char = char
        self.children = {}
        self.word = False

class Trie:
    def __init__(self):
        self.root = Node(\"\")

    def add_word(self, word):
        def helper(next_idx, node):
            next_char = word[next_idx]
            if next_char not in node.children:
                node.children[next_char] = Node(next_char)
            node = node.children[next_char]
            if next_idx == len(word) - 1:
                node.word = True
            else:
                helper(next_idx+1, node)
        helper(0, self.root)

    def prefix_of_word_exists(self, word):
        idx = 0
        node = self.root
        for char in word:
            if char not in node.children:
                return False
            node = node.children[char]
            if node.word:
                return True
        return False
        

class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.max_word_length = 0
        for word in words:
            self.trie.add_word(word[::-1])
            self.max_word_length = max(self.max_word_length, len(word))
        self.q = deque()

    def query(self, letter: str) -> bool:
        if len(self.q) == self.max_word_length:
            self.q.pop()
        self.q.appendleft(letter)
        return self.trie.prefix_of_word_exists(self.q)
    # [\"cde\"]
    # [\"c\" Node<d>, \"d\" None] e
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self):
        self.children, self.end_node = {}, 0
         
class Trie:
    def __init__(self):
        self.root = TrieNode()

    def insert(self, word):
        root = self.root
        for symbol in word:
            root = root.children.setdefault(symbol, TrieNode())
        root.end_node = 1

class StreamChecker:
    def __init__(self, words):
        self.trie = Trie()
        self.Stream = deque()
        for word in words: self.trie.insert(word[::-1])
         
    def query(self, letter):
        self.Stream.appendleft(letter)
        cur = self.trie.root
        for c in self.Stream:
            if c in cur.children:
                cur = cur.children[c]
                if cur.end_node: return True
            else: break
        return False

from collections import deque
from typing import Dict

class Trie:
    def __init__(self):
        self.d = {}
    
    def ends(self) -> bool:
        return \"$\" in self.d
    
    def absent(self, c) -> bool:
        return c not in self.d
    
    def getTrie(self, c):
        return self.d[c]
    
    def addWord(self, word: str) -> None:
        if not word:
            self.d[\"$\"] = None
            return
        if word[0] not in self.d:
            self.d[word[0]] = Trie()
        self.d[word[0]].addWord(word[1:])

class StreamChecker:

    def __init__(self, words: List[str]):
        self.max_len = max(map(len, words))
        self.suffix_trie = self.build_tree(words)
        self.queue = deque([])
    
    def build_tree(self, words: List[str]) -> Dict[str, Trie]:
        trie: Trie = Trie()
        for word in words:
            trie.addWord(word[::-1])
        return trie

    def query(self, letter: str) -> bool:
        # if self.max_len == self.curr_len:
        #     self.queue.popleft()
        self.queue.appendleft(letter)
        i = 0
        n = self.suffix_trie
        while i < len(self.queue):
            if n.ends():
                return True
            if n.absent(self.queue[i]):
                return False
            n = n.getTrie(self.queue[i])
            i += 1
        return n.ends()
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:
  def __init__(self, words: List[str]):
    self.string = collections.deque()
    self.root = {}
    for word in words:
      node = self.root
      for c in word[::-1]:
        if c not in node:
          node[c] = {}
        node = node[c]
      node['#'] = 1

  def query(self, letter: str) -> bool:
    self.string.appendleft(letter)
    node = self.root
    for c in self.string:
      if c in node:
        node = node[c]
        if '#' in node:
          return True
      else:
        return False
    return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie(defaultdict):
    #def __init__(self):
    #        self.root = self
            #self.eow = False
            
    def addWord(self,word):
        curr = self
        for ch in word:
            if ch not in curr:
                curr[ch] = Trie()   
            curr = curr[ch]
        curr['*'] = True   
        
    def searchWord(self,word) -> bool:
        curr = self
        #print(word)
        for ch in word:
            if ch in curr:
                curr = curr[ch]   
            else:
                return False    
            if '*' in curr:
                return True  
        return False   
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.maxLen = 0
        for word in words:
            self.maxLen = max(self.maxLen, len(word))
            self.trie.addWord(word[::-1])
            
        #print(self.trie)    
        self.history = []

    def query(self, letter: str) -> bool:
        if len(self.history) == self.maxLen:
            self.history.pop(0)
        self.history.append(letter)    
        return self.trie.searchWord(''.join(self.history[::-1]))
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie():
    def __init__(self):
        self.children = [None]*26
        self.endOfWord = False
        
    def insert(self, s):
        curr = self
        for c in s:
            if curr.children[ord(c) - ord('a')] == None:
                curr.children[ord(c) - ord('a')] = Trie()
            curr = curr.children[ord(c) - ord('a')]
        curr.endOfWord = True
        
    def search(self, s):
        curr = self
        for c in s:
            if curr.children[ord(c) - ord('a')] == None:
                return False
            curr = curr.children[ord(c) - ord('a')]
            if curr.endOfWord == True:
                return True
        return False
    
class StreamChecker:

    def __init__(self, words: List[str]):
        self.t = Trie()
        self.stream = collections.deque()
        for w in words:
            self.t.insert(reversed(w))

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        return self.t.search(self.stream)
    
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


# https://leetcode.com/problems/stream-of-characters/discuss/320837/Easily-implemented-Python-Trie-Solution
# Trie implemented based on defaultdict get TLE, originial Python dict won't get
class TrieNode:
    def __init__(self) -> None:
        self.children = {}
        self.isWord = False
    
class Trie:
    def __init__(self) -> None:
        self.root = TrieNode()
    
    def insert(self, word: str) -> None:
        current = self.root
        for letter in word:
            if letter not in current.children:
                current.children[letter] = TrieNode()
            current = current.children[letter]
        current.isWord = True

class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.queries = []
        for word in words:
            self.trie.insert(word[::-1])

    def query(self, letter: str) -> bool:
        self.queries.append(letter)
        idx = len(self.queries) - 1
        current = self.trie.root
        while idx >= 0:
            letter = self.queries[idx]
            if letter not in current.children:
                return False
            current = current.children[letter]
            if current.isWord:
                return True
            idx -= 1
        return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.tries = {}
        self.hist = []
        for word in words:
            cur = self.tries            
            for c in word[::-1]:
                if c not in cur:
                    cur[c] = {}
                cur = cur[c]
            cur['#'] = word

    def query(self, letter: str) -> bool:
        self.hist.insert(0, letter) 
        cur = self.tries
        for c in self.hist:
            if '#' in cur:
                return True
            if c in cur:
                cur = cur[c]
            else:
                return False
        return '#' in cur

    
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def build_trie(self, words):
        for word in words:
            w = word[::-1]
            curr = self.trie
            for l in w:
                if curr[ord(l)-ord('a')]:
                    curr = curr[ord(l)-ord('a')]
                else:
                    curr[ord(l)-ord('a')] = [[] for i in range(27)]
                    curr = curr[ord(l)-ord('a')]
            curr[26] = 1
    
    def __init__(self, words: List[str]):
        self.trie = [[] for i in range(27)]
        self.mlength = max([len(w) for w in words])
        self.mem = ''
        self.build_trie(words)

    def query(self, letter: str) -> bool:
        if len(self.mem) < self.mlength:
            self.mem += letter
        else:
            self.mem = self.mem[1:] + letter
        w = self.mem[::-1]
        curr = self.trie
        for l in w:
            if curr[26]:
                return True
            if curr[ord(l)-ord('a')]:
                curr = curr[ord(l)-ord('a')]
            else:
                return False
        if curr[26]:
                return True
        else:
            return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    
    def __init__(self):
        self.endOfWord = False
        self.children = [None]*26

    def insert(self, s):
        t = self
        for c in s:
            if t.children[ord(c)-ord('a')] == None:
                t.children[ord(c)-ord('a')] = Trie()
            t = t.children[ord(c)-ord('a')]
        t.endOfWord = True

    def search(self, s):
        t = self
        for c in s:
            if t.children[ord(c)-ord('a')] == None: return False
            t = t.children[ord(c)-ord('a')]
            if t.endOfWord: return True
        return False


class StreamChecker:

    def __init__(self, words: List[str]):
        self.t = Trie()
        self.stream = collections.deque()
        for w in words:
            self.t.insert(reversed(w))

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        return self.t.search(self.stream)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    def __init__(self):
        self.children = {}
        self.isEnd = False
    
    def insert(self, word):
        if len(word)==0:
            self.isEnd = True
            return
        if word[0] not in self.children:
            self.children[word[0]] = Trie()
        self.children[word[0]].insert(word[1:])
        
    def search(self, word):
        if len(word)==0:
            return (True, False)
        if len(word)==1:
            return (word[0] in self.children, word[0] in self.children and self.children[word[0]].isEnd)
        startsWith = word[0] in self.children
        if startsWith:
            return self.children[word[0]].search(word[1:])

        return (False, False)

    def startsWith(self, word):
        if len(word)==0:
            return True
        return word[0] in self.children and self.children[word[0]].startsWith(word[1:])
    def next(self, char):
        if char in self.children:
            return self.children[char]
        return None
    def printNode(self):
        print(self.children,self.isEnd)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.words = Trie()
        for word in words:
            self.words.insert(word[::-1])
        self.stream = \"\"

    def query(self, letter: str) -> bool:
        self.stream += letter
        node = self.words
        for i in range(len(self.stream)-1, -1, -1):
            node = node.next(self.stream[i])
            if node==None:
                return False
            if node.isEnd:
                return True
            
                
        return False
    
                
                
                
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.maxn = max([len(x) for x in words])
        self.suffix = set()
        self.words = set(words)
        for i in words:
            for j in range(len(i)-1, -1, -1):
                self.suffix.add(i[j:])
        self.queue = []

    def query(self, letter: str) -> bool:
        if len(self.queue) >= self.maxn:
            self.queue.pop(0)
        self.queue.append(letter)
        st = ''
        for i in range(len(self.queue) -1, -1, -1):
            st = self.queue[i] + st
            if st in self.words:
                return True 
            elif st not in self.suffix:
                return False 
        return False 


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Node:
    
    def __init__(self, flag=False):
        self.flag = False
        self.a = [None] * 26
    
    def insert(self, s, p):
        if p == len(s):
            self.flag = True
            return
        c = ord(s[p]) - ord('a')
        if self.a[c] is None:
            self.a[c] = Node()
        self.a[c].insert(s, p + 1)
        
    def query(self, s, p):
        if p == -1:
            return False
        c = ord(s[p]) - ord('a')
        if self.a[c] is None:
            return False
        if self.a[c].flag:
            return True
        return self.a[c].query(s, p - 1)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.node = Node()
        self.s = []
        for word in words:
            self.node.insert(word[::-1], 0)

    def query(self, letter: str) -> bool:
        self.s.append(letter)
        return self.node.query(self.s, len(self.s) - 1)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode():
    def __init__(self):
        self.children = {}
        self.isEnd = False

class Trie():
    def __init__(self):
        self.root = TrieNode()
    
    def insert(self, word):
        node = self.root
        for char in word:
            if char not in node.children:
                node.children[char] = TrieNode()
            node = node.children[char]
        node.isEnd = True

class StreamChecker:
    def __init__(self, words: List[str]):
        self.letters = []
        self.trie = Trie()
        for w in words:
            self.trie.insert(w[::-1])
        
    def query(self, letter: str) -> bool:
        self.letters.append(letter)
        i = len(self.letters) - 1
        node = self.trie.root
        while i >= 0:
            if node.isEnd:
                return True
            if self.letters[i] not in node.children:
                return False
            node = node.children[self.letters[i]]
            i -= 1
        return node.isEnd

class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = {}
        self.stream = collections.deque()
        for word in words:
            node = self.root
            for ch in word[::-1]:
                if ch not in node:
                    node[ch] = {}
                node = node[ch]
            node['#'] = {}
        # print(self.root)
        
    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        node = self.root
        # print('=>', letter)
        for ch in self.stream:
            if ch in node:
                # print(ch)
                node = node[ch]
                if '#' in node:
                    return True
            else:
                return False
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import defaultdict

class StreamChecker:

    def __init__(self, words: List[str]):
        self.wlookup = defaultdict(set)
        self.llookup = defaultdict(set)
        self._buf = \"\"
        
        for w in words:
            self.wlookup[w[-1]].add(w[::-1])
            self.llookup[w[-1]].add(len(w))
        
        

    def query(self, letter: str) -> bool:
        self._buf = \"\".join((letter, self._buf))
        
        #print(self.wlookup, self.llookup, self._buf, letter)
        
        if letter not in self.wlookup:
            return False
        
        for l in self.llookup[letter]:
            if self._buf[:l] in self.wlookup[letter]:
                return True
        return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self):
        self.word = False
        self.children = {}
        
class Trie:
    def __init__(self):
        self.root = TrieNode()
        
    def insert(self, word):
        node = self.root
        for w in word:
            if w not in node.children:
                node.children[w] = TrieNode()
            node = node.children[w]
        node.word = True
    
class StreamChecker:
    def __init__(self, words: List[str]):
        self.letters = []
        self.trie = Trie()
        for word in words:
            self.trie.insert(word[::-1])

    def query(self, letter: str) -> bool:
        self.letters.append(letter)
        i = len(self.letters) - 1
        node = self.trie.root
        while i >= 0:
            if node.word == True:
                return True
            if self.letters[i] not in node.children:
                return False
            node = node.children[self.letters[i]]
            i -= 1
        return node.word

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.next = {}
        self.is_word = False
        
class StreamChecker:
    def __init__(self, words: List[str]):
        self.root = TrieNode()
        for word in words:
            itr = self.root
            for c in word[::-1]:
                itr.next.setdefault(c, TrieNode())
                itr = itr.next[c]
            itr.is_word = True
        self.stream = deque()

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        curr = self.root
        for c in self.stream:
            if c in curr.__next__:
                curr = curr.next[c]
                if curr.is_word:
                    return True
            else:
                break
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.word_tree = dict()
        self.stream = []
        self.min_len = float(\"inf\")
        
        rev_words = sorted([word[::-1] for word in words])
        
        for word in rev_words:
            self.min_len = min(self.min_len, len(word))
            cur_dict = self.word_tree
            for c in word[:-1]:
                if c not in cur_dict:
                    cur_dict[c] = (False, dict())
                    
                cur_dict = cur_dict[c][1]
                
            if word[-1] not in cur_dict:
                cur_dict[word[-1]] = (True, dict())
            else:
                last_entry = cur_dict[word[-1]]
                cur_dict[word[-1]] = (True, last_entry[1])
                

    def query(self, letter: str) -> bool:
        self.stream.insert(0, letter)
        
        if len(self.stream) < self.min_len: return False
        
        cur_dict = self.word_tree
        for c in self.stream:
            if c in cur_dict and cur_dict[c][0]:
                return True
            elif c in cur_dict:
                cur_dict = cur_dict[c][1]
            else:
                return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TreeNode:
    def __init__(self,chr):
        self.val = chr
        self.children = {}
        self.leaf = False



class StreamChecker:

    def __init__(self, words: List[str]):
        \"\"\"
        Initialize your data structure here.
        \"\"\"
        self.root = TreeNode(None)
        for word in words:
            self.insert(''.join(reversed(word)))
        self.ans=''

    def insert(self, word: str) -> None:
        \"\"\"
        Inserts a word into the trie.
        \"\"\"
        parent = self.root
        for c in word:
            if(c not in parent.children):
                parent.children[c] = TreeNode(c)
            parent = parent.children[c]
        parent.leaf = True
        

    def search(self, word: str) -> bool:
        \"\"\"
        Returns if the word is in the trie.
        \"\"\"
        parent = self.root
        for c in word:
            if(c not in parent.children):
                return False
            parent = parent.children[c]
            if(parent.leaf):
                return True
        return False
                
          

    def query(self, letter: str) -> bool:
        self.ans=letter+self.ans
        return self.search(self.ans)
        
            
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self):
        self.children = {}
        self.ends_here = False

        
class Trie:
    def __init__(self):
        self.root = TrieNode()
        
        
    def insert(self, word):
        curr = self.root
        
        for c in word:
            curr = curr.children.setdefault(c, TrieNode())
            
        curr.ends_here = True


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.queue = deque()
        for word in words:
            self.trie.insert(word[::-1])

    def query(self, letter: str) -> bool:
        self.queue.appendleft(letter)
        curr = self.trie.root
        
        for c in self.queue:
            if c in curr.children:
                curr = curr.children[c]
                if curr.ends_here:
                    return True
                
            else:
                break
                
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import deque

class TrieNode:
    def __init__(self):
        self.children = [None]*26
        self.eow = False

class Trie:
    def __init__(self):
        self.root = TrieNode()
        
    def charToIndex(self, _char):
        return ord(_char) - ord('a')
    
    def insert(self, word):
        node = self.root
        l = len(word)
        for i in range(l):
            idx = self.charToIndex(word[i])
            if node.children[idx] == None:
                node.children[idx] = TrieNode()
            node = node.children[idx]
        node.eow = True
        
    def search(self, word):
        node = self.root
        l = len(word)
        for i in range(l):
            idx = self.charToIndex(word[i])
            if node.children[idx] != None:
                node = node.children[idx]
            else:
                return False
            if node.eow:
                return True
        return node!=None and node.eow


class StreamChecker:
    def __init__(self, words: List[str]):
        self.words = words
        self.trie = Trie()
        for word in self.words:
            # print(word[::-1])
            self.trie.insert(word[::-1])

        self.longest = len(max(words, key=len))
        self.data = deque([], maxlen=self.longest)
        

    def query(self, letter: str) -> bool:
        if self.data.count == self.longest:
                popped = self.data.pop()
        self.data.appendleft(letter)
        # print(\"\".join(self.data))
        if self.trie != None and self.trie.root.children[ord(letter)-ord('a')] != None:
            return self.trie.search(\"\".join(self.data))
        else:
            return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = {}
        self.stream = []
        self.word_end = -1
        for word in words:
            cur_node = self.root
            for char in word[::-1]:
                cur_node.setdefault(char, {})
                cur_node = cur_node[char]
            cur_node[self.word_end] = True
        
    def query(self, letter: str) -> bool:
        self.stream.insert(0, letter)
        cur_node = self.root
        for char in self.stream:
            if char not in cur_node:
                return False
            else:
                cur_node = cur_node[char]
                if self.word_end in cur_node:
                    return True
        return False
            
            
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    
    def __init__(self):
        self.endOfWord = False
        self.children = [None] * 26
        
    def insert(self, s):
        t = self
        for c in s:
            if (t.children[ord(c) - ord('a')] == None):
                t.children[ord(c) - ord('a')] = Trie()
            t = t.children[ord(c) - ord('a')]
        t.endOfWord = True
        
    def search(self, s):
        t = self
        for c in s:
            if (t.children[ord(c) - ord('a')] == None):
                return False
            t = t.children[ord(c) - ord('a')]
            if t.endOfWord:
                return True
        return False
                

class StreamChecker:

    def __init__(self, words: List[str]):
        self.t = Trie()
        self.stream = collections.deque()
        for w in words:
            self.t.insert(reversed(w))

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        return self.t.search(self.stream)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.stream = deque([])
        
        # O(NM) time and space N=len(words), M = wordlen #
        for w in words:
            node = self.trie
            for c in w[::-1]:
                if c not in node:
                    node[c] = {}
                node = node[c]
            node['$'] = w

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        
        # O(M) time and space 
        node = self.trie
        for c in self.stream:
            if '$' in node:
                return True
            if c not in node:
                return False
            node = node[c]
        return '$' in node
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import defaultdict
from functools import reduce

class StreamChecker:

    def __init__(self, words: List[str]):
        # O(N x M)

        self.s = \"\"
        self.dic = defaultdict(set)
        for w in words:
            self.dic[w[-1]].add(w)
        

    def query(self, letter: str) -> bool:
        # O(M) where M is a max word length.

        self.s += letter
        return any(self.s.endswith(w) for w in self.dic[letter])
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Trie:
    d = {}
    record = {}

    def __init__(self):
        self.record = {}
        self.d = {}

    def add(self, word):
        if len(word) == 1:
            if word[0] not in self.d:
                self.d[word[0]] = Trie()
                self.d[word[0]].d[-1] = 1
                return
            else:
                self.d[word[0]].d[-1] = 1
                return

        letter = word[-1]
        if letter in self.d:
            self.d[letter].add(word[:-1])
            return

        self.d[letter] = Trie()
        self.d[letter].add(word[:-1])
        return
    
    def search(self, ls, index):
        if index in self.record:
            return self.record[index]
        
        val = False
        if -1 in self.d:
            val = True
        
        elif index < 0:
            val = False
        
        elif ls[index] in self.d:
            val = self.d[ls[index]].search(ls, index - 1)
        
        self.record[index] = val
        
        return val
    
class StreamChecker:
    root = None
    l = None
    size = 0
    def __init__(self, words: List[str]):
        self.root = Trie()
        self.l = collections.deque()
        self.size = 0
        for i in words:
            self.root.add(i)
            

    def query(self, letter: str) -> bool:
        self.size += 1
        self.l.append(letter)
        #print(letter)
        return self.root.search(self.l, self.size - 1)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    def __init__(self):
        self.children = dict()
        self.isend = False
    
    def insert(self, word):
        cur = self
        for ch in word:
            if ch not in cur.children:
                cur.children[ch] = Trie()
            cur = cur.children[ch] 
        cur.isend = True
    
    def hasPrefix(self, stream):
        cur = self
        for ch in stream:
            if ch not in cur.children:
                return False
            cur = cur.children[ch] 
            if cur.isend:
                return True
        return cur.isend

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.longest = 0
        for w in words:
            self.longest = max(self.longest, len(w))
            self.trie.insert(w[::-1])
        self.stream = deque()
        
    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        if len(self.stream) > self.longest:
            self.stream.pop()
        return self.trie.hasPrefix(''.join(self.stream))


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)



class TrieNode:
    def __init__(self):
        self.children, self.end_node = {}, 0
         
class Trie:
    def __init__(self):
        self.root = TrieNode()

    def insert(self, word):
        root = self.root
        for symbol in word:
            root = root.children.setdefault(symbol, TrieNode())
        root.end_node = 1

class StreamChecker:
    def __init__(self, words):
        self.trie = Trie()
        self.Stream = deque()
        for word in words: self.trie.insert(word[::-1])
    
    def query(self, letter):
        self.Stream.appendleft(letter)
        cur = self.trie.root
        for c in self.Stream:
            if c in cur.children:
                cur = cur.children[c]
                if cur.end_node: return True
            else: break
        return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import deque
class TrieNode:
    def __init__(self):
        self.children = {}
        self.isEndWord = False

class Trie:
    def __init__(self):
        self.root = TrieNode()

    def addWord(self, word):
        head = self.root
        for char in word:
            head = head.children.setdefault(char, TrieNode())
        head.isEndWord = True


class StreamChecker:
    def __init__(self, words):
        self.vocab = Trie()
        self.queue = deque()
        for word in words:
            self.vocab.addWord(word[::-1])

    def query(self, char):
        self.queue.appendleft(char)
        cur = self.vocab.root
        for c in self.queue:
            if c in cur.children:
                cur = cur.children[c]
                if cur.isEndWord:
                    return True
            else:
                break
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)



class Node:
    def __init__(self):
        self.word = False 
        self.children = {}

class StreamChecker:

    def __init__(self, words: List[str]):
        
        self.words = words
        self.word = \"\"
        self.head = Node()
        for word in words:
            word = word[::-1]
            ptr = self.head
            for cha in word:
                if cha not in ptr.children:
                    ptr.children[cha] = Node()
                ptr = ptr.children[cha]
            ptr.word = True 
                    

    def query(self, letter: str) -> bool:
        self.word+=letter 
        
        length = len(self.word)
        ptr = self.head 
        for i in range(length-1, -1, -1):
            if self.word[i] not in ptr.children:
                return False 
            ptr = ptr.children[self.word[i]]
            if ptr.word:
                return True 
        return False 
        
        
            
            
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Node:
    def __init__(self):
        self.children = collections.defaultdict(Node)
        self.isStart = False
        
        
class Trie:
    def __init__(self, words: List[str]):
        self.root = Node()
        self.maxLen = 0
        
        for word in words:
            self.maxLen = max(self.maxLen, self.insert(word))
            
    def insert(self, word: str) -> int:
        i = 0
        current = self.root
        for char in word[::-1]:
            current = current.children[char]
            i += 1
            
        current.isStart = True
        return i
    
    def endsWith(self, word: str) -> bool:
        current = self.root
        for char in word:
            if current.isStart:
                return True
            if char not in current.children:
                return False
            current = current.children[char]
            
        return current.isStart
        
        
class StreamChecker:
    def __init__(self, words: List[str]):
        self.wl = Trie(words)
        self.bufSize = self.wl.maxLen
        self.history = collections.deque()

    def query(self, letter: str) -> bool:
        self.history.appendleft(letter)
        if len(self.history) > self.bufSize:
            self.history.pop()  
            
        return self.wl.endsWith(''.join(self.history))


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import defaultdict
class StreamChecker:

    def __init__(self, words: List[str]):
        self.words = defaultdict(list)
        for word in words:
            self.words[word[-1]].append(word)
        self.l = ''
        

    def query(self, letter: str) -> bool:
        self.l += letter
        for i in self.words[letter]:
            if self.l.endswith(i):
                return True
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import defaultdict
import queue 
class TrieNode():
    def __init__(self):
        self.children = defaultdict(TrieNode)

class StreamChecker:
    def __init__(self, words: List[str]):
        self.root = TrieNode()
        self.cstream = []
        for word in words:
            curr = self.root
            for c in word[::-1]:
                curr = curr.children[c]
            curr = curr.children['$']
    
    def query(self, letter: str) -> bool:
        self.cstream.insert(0,letter)
        curr = self.root
        for c in self.cstream:
            if '$' in curr.children:
                return True
            if c not in curr.children:
                return False
            curr = curr.children[c]
        return '$' in curr.children
        pass


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    def __init__(self):
        self.child = {}
        self.isEnd = False;


class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = Trie()
        self.str = []
        
        for word in words:
            node = self.root
            for ch in reversed(word):
                if ch not in node.child:
                    node.child[ch] = Trie()
                node = node.child[ch]
            node.isEnd = True

    def query(self, letter: str) -> bool:
        self.str.insert(0, letter)
        
        node = self.root
        for ch in self.str:
            if ch not in node.child:
                return False
            node = node.child[ch]
            if node.isEnd:
                return True
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    \"\"\"
    cd, f, kl, 
           ^
    
    
    trie{
        d: {
            c: {
                $: True
            }
            },        
        f: {
            $: True   
            }        
        k: {
          l: {
            $: True
            }
            }
    }
    
    queue = [a, b, c, d]
                      ^
                      
            dcba
            ^
    \"\"\"
    def __init__(self, words: List[str]):
        self.trie = {} 
        self.stream = []
        for word in words:
            node = self.trie
            for letter in reversed(word):
                if letter not in node:
                    node[letter] = {}
                node = node[letter]
            node['$'] = True                        

    def query(self, letter: str) -> bool:
        self.stream.append(letter)
        node = self.trie
        for letter in reversed(self.stream):            
            if letter in node:
                node = node[letter]
                if \"$\" in node:
                    return True
            else:
                return False
        return False
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self):
        self.isWord=False
        self.child = {}

class Trie:
    def __init__(self):
        self.root = TrieNode()
        
    def add_word(self, word):
        cur = self.root
        for i in range(len(word)):
            if word[i] not in cur.child:
                cur.child[word[i]]=TrieNode()
            cur =cur.child[word[i]]
        cur.isWord=True
    
    def search_word(self, word):
        cur=self.root
        for i in range(len(word)):
            if word[i] not in cur.child:
                return False
            else:
                cur=cur.child[word[i]]
        return cur.isWord
             
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie=Trie()
        self.max_length = max(len(word) for word in words)
        self.letters =collections.deque()
        for word in words:
            self.trie.add_word(word[::-1])

    def query(self, letter: str) -> bool:
        self.letters.append(letter)
        if len(self.letters)>self.max_length:
            self.letters.popleft()
        
        t = list(self.letters)[::-1]
        cur = self.trie.root
        for letter in t:
            if letter not in cur.child:
                return False
            cur=cur.child[letter]
            if cur.isWord:
                return True
        return False
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.memo = {}
        self.words = set()
        words_ = [word[::-1] for word in words]
        for word in words_:
            for i in range(len(word)-1):
                self.memo[word[:i+1]]=0
        
        for word in words_:
            self.memo[word]=1     
        
        self.hist = []
        
        #print(self.memo)
    
    def query(self, letter: str) -> bool:
        self.hist.append(letter)
        w = ''
        for i in range(len(self.hist)-1,-1,-1):
            w+=self.hist[i]
            #print(w)
            c = self.memo.get(w,None)
            if c is None:
                return False
            if c:
                return True
            
        return False


class TrieNode:
    def __init__(self):
        self.edges={}
    
    def get_edge(self,edge):
        return self.edges[edge]
    
    def add_edge(self,edge):
        self.edges.setdefault(edge,TrieNode())
            
    def has_edge(self,edge):
        return edge in self.edges
    
    def isWord(self):
        return \"$\" in self.edges
    
class Trie:
    
    def __init__(self):
        self.root=TrieNode()
        
    def insert(self,word):
        cur=self.root
        for c in word:
            cur.add_edge(c)
            cur=cur.get_edge(c)
        cur.add_edge(\"$\")
        
    def search(self, word):
        cur=self.root
        for c in word:
            if cur.isWord():
                return True
            if not cur.has_edge(c):
                return False
            cur=cur.get_edge(c)
        return cur.isWord()
from collections import deque
class StreamChecker:
    def __init__(self, W):
        self.prefix=deque()
        self.trie=Trie()
        for w in W:
            self.trie.insert(w[::-1])

    def query(self, c):
        self.prefix.appendleft(c)
        return self.trie.search(self.prefix)


\"\"\"
time:  9:00AM
challenge2:  Can I learn how to use setdefault in this problem.  

\"\"\"
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.memo = set()
        self.words = set()
        for word in words:
            word_ = word[::-1]
            for i in range(len(word)-1):
                self.memo.add(word_[:i+1])
            self.words.add(word_)        
        self.hist = []
        
        print((self.memo))
    
    def query(self, letter: str) -> bool:
        self.hist.append(letter)
        w = ''
        for i in range(len(self.hist)-1,-1,-1):
            w+=self.hist[i]
            #print(w)
            if w in self.words:
                return True
            if w not in self.memo:
                return False
            
        return False




class TreeNode:
    def __init__(self, val=0):
        self.val = 0
        self.children = [None] * 26
        
class StreamChecker:
    
    def __init__(self, words: List[str]):
        self.root = TreeNode(0)
        for word in words:
            word = word[::-1]
            current = self.root
            for letter in word:
                temp = current.children[ord(letter) - ord('a')]
                if temp is None:
                    new = TreeNode(0)
                    current.children[ord(letter) - ord('a')] = new
                    current = new
                else:
                    current = temp
            current.val = 1
        self.query_str = ''
        
    def query(self, letter: str) -> bool:
        self.query_str = letter + self.query_str
        return self.search()

    def search(self):
        current = self.root
        for letter in self.query_str:
            temp = current.children[ord(letter) - ord('a')]
            if temp is None:
                return False
            else:
                if temp.val == 1:
                    return True
                else:
                    current = temp
            
        
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    def __init__(self):
        self.child = {}
        self.isEnd = False
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = Trie()
        self.str = []
        
        for word in words:
            node = self.root
            for ch in reversed(word):
                if ch not in node.child:
                    node.child[ch] = Trie()
                node = node.child[ch]
            node.isEnd = True
        

    def query(self, letter: str) -> bool:
        self.str.insert(0, letter)
        
        node = self.root
        for ch in self.str:
            if ch not in node.child:
                return False
            node = node.child[ch]
            if node.isEnd:
                return True
            
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Node:
    
    def __init__(self):
        self.child={}
        self.isword=False

        
class Trie:
    
    def __init__(self):
        self.root=Node()
        
    def addword(self,word):
        node=self.root
        for char in word:
            if char not in node.child:
                node.child[char]=Node()
            node=node.child[char]
        node.isword=True
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.Trie=Trie()
        for word in words:
            self.Trie.addword(word[::-1])
        self.queue=[]

    def query(self, letter: str) -> bool:
        self.queue.insert(0,letter)
        node=self.Trie.root
        for char in self.queue:
            if char not in node.child:
                return False
            else:
                node=node.child[char]
                if node.isword:
                    return True
        return False
                

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    def __init__(self):
        self.node = TrieNode()
        
    def add(self,wordadd):
        node = self.node
        for char in wordadd:
            if char not in node.child:
                node.child[char] = TrieNode()
            node = node.child[char]
        node.isEnd = True

class TrieNode:
    def __init__(self):
        self.child = {}
        self.isEnd = False
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.letters = []
        self.rootNode = Trie()
        for word in words:
            self.rootNode.add(word[::-1])
            
    def query(self, letter: str) -> bool:
        self.letters.insert(0,letter)
        node = self.rootNode.node
        for letter in self.letters:
            if node.isEnd:
                return True
            if letter not in node.child:
                return False
            node = node.child[letter]
        return node.isEnd

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.history = collections.deque()
        self.N = 0
        for word in words:
            self.N = max(self.N, len(word))
            rword = word[::-1]
            node = self.trie
            for ch in rword:
                if ch not in node:
                    node[ch] = {}
                node = node[ch]
            node[\"#\"] = {}

    def query(self, letter: str) -> bool:
        self.history.appendleft(letter)
        if len(self.history) > self.N:
            self.history.pop()
        node = self.trie
        for ch in self.history:
            if ch not in node:
                return False
            node = node[ch]
            if \"#\" in node:
                return True
        return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = TrieNode()
        self.buffer = ''
        self.letters = []
        for word in words:
            word = word[::-1]
            node = self.root
            for c in word:
                node = node.children[c]
            node.isEnd = True

    def query(self, letter: str) -> bool:
        self.letters.append(letter)
        i = len(self.letters)-1
        node = self.root
        while i >= 0:
            if node.isEnd:
                return True
            if self.letters[i] not in node.children:
                return False
            node = node.children[self.letters[i]]
            i-=1
        return node.isEnd
    
class TrieNode:
    def __init__(self):
        self.children = defaultdict(TrieNode)
        self.isEnd = False

    
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Node:
    def __init__(self, val=None, children={}, is_end=False):
        self.val = val
        self.children = children
        self.is_end = is_end

class StreamChecker:
    def __add_word(self, word):
        curr = self.root
        #print(\"word\", word)
        for char in word[::-1]:
            #print(\"char\", char)
            if char not in curr.children:
                curr.children[char] = Node(val=char,children={},is_end=False)
            curr = curr.children[char]
        curr.is_end = True
    def __init__(self, words: List[str]):
        self.root = Node(None,{},False)
        self.buffer = []
        for word in words:
            self.__add_word(word)
    def __is_present_k(self):
        curr = self.root
        #print(\"buffer\", self.buffer)
        for char in self.buffer:
            #print(\"char\", char)
            #print(\"curr children\", [ curr.children[temp].val for temp in curr.children] )
            if char not in curr.children:
                return False
            curr = curr.children[char]
            if curr.is_end:
                return True
        return False
    def query(self, letter: str) -> bool:
        self.buffer.insert(0,letter)
        return self.__is_present_k()

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
  def __init__(self, words: List[str]):
    self.s = ''
    self.maxLen = max(len(word) for word in words)
    
    self.dic = defaultdict(set)
    
    for word in words:
      self.dic[word[-1]].add(word)

  def query(self, letter: str) -> bool:
    self.s += letter
    self.s = self.s[-self.maxLen:]
    return any(self.s.endswith(w) for w in self.dic[letter])


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


import collections

class Trie:
    def __init__(self):
        self.children = [None]*26
        self.isEnd = False
        
    def add_word(self, word):
        curr = self
        for c in word:
            if curr.children[ord(c) - ord('a')] == None:
                curr.children[ord(c) - ord('a')] = Trie()
            curr = curr.children[ord(c) - ord('a')]
        curr.isEnd = True
        
    def search(self, word):
        curr = self
        for c in word:
            if curr.children[ord(c) - ord('a')] == None: return False
            curr = curr.children[ord(c) - ord('a')]
            if curr.isEnd: return True
        return False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.stream = collections.deque()
        for w in words:
            self.trie.add_word(w[::-1])

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        return self.trie.search(self.stream)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.children, self.end_node = {}, 0

    
class Trie:
    def __init__(self, ):
        self.root = TrieNode()

    def insert(self, word):
        root = self.root

        for symbol in word:
            root = root.children.setdefault(symbol, TrieNode())

        root.end_node = 1

        
class StreamChecker:        

    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.stream = deque()
        for word in words:
            self.trie.insert(word[::-1])
            
    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        current = self.trie.root
        
        for char in self.stream:
            if char in current.children:
                current = current.children[char]
                if current.end_node:
                    return True
            else:
                break
        
        return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.memo = {}
        self.words = set()
        words_ = [word[::-1] for word in words]
        for word in words_:
            for i in range(len(word)-1):
                self.memo[word[:i+1]]=0
        
        for word in words_:
            self.memo[word]=1
        
        self.hist = []
        
        #print(self.memo)
    
    def query(self, letter: str) -> bool:
        self.hist.append(letter)
        w = ''
        for i in range(len(self.hist)):
            w+=self.hist[-i-1]
            #print(w)
            c = self.memo.get(w,None)
            if c is None:
                return False
            if c:
                return True
            
        return False



class Trie:
    
    def __init__(self):
        self.endOfWord = False
        self.children = [None]*26

    def insert(self, s):
        t = self
        for c in s:
            if t.children[ord(c)-ord('a')] == None:
                t.children[ord(c)-ord('a')] = Trie()
            t = t.children[ord(c)-ord('a')]
        t.endOfWord = True

    def search(self, s):
        t = self
        for c in s:
            if t.children[ord(c)-ord('a')] == None: 
                return False
            t = t.children[ord(c)-ord('a')]
            if t.endOfWord: return True
        return False


class StreamChecker:

    def __init__(self, words: List[str]):
        self.t = Trie()
        self.stream = collections.deque()
        for w in words:
            self.t.insert(reversed(w))

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        return self.t.search(self.stream)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieHolder:
    def __init__(self):
        self.flag=0
        self.next=[None]*26

class StreamChecker:
    
    def __init__(self, words: List[str]):
        self.root = TrieHolder()
        for i in words:
            self.insert(i[::-1])
        self.searchLetters=[]
        self.l=0
    
    def insert(self, word: str) -> None:
        t=self.root
        for i in word:
            if t.next[ord(i)-97] == None:
                t.next[ord(i)-97]=TrieHolder()
            t=t.next[ord(i)-97]
        t.flag=1
        
    def query(self, letter: str) -> bool:
        self.searchLetters.append(letter)
        self.l+=1
        t=self.root
        for j in range(self.l-1,-1,-1):
            letter=self.searchLetters[j]
            if t.next[ord(letter)-97]==None:
                return False
            elif t.next[ord(letter)-97].flag==1:
                return True
            else:
                t=t.next[ord(letter)-97]
        return False
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.s = ''
        self.dic = collections.defaultdict(set)
        for w in words:
            self.dic[w[-1]].add(w)
                

    def query(self, letter: str) -> bool:
        self.s += letter
        return any(self.s.endswith(w) for w in self.dic[letter])
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.children = [None]*26
        self.eow = False

class Trie:
    def __init__(self):
        self.root = TrieNode()

    def insert(self, key):
        pCrawl = self.root

        length = len(key)
        for i in range(length):
            if pCrawl.children[ord(key[i])-ord('a')] is None:
                pCrawl.children[ord(key[i])-ord('a')] = TrieNode()
            
            pCrawl = pCrawl.children[ord(key[i])-ord('a')]
        
        pCrawl.eow = True
    
    def search(self, key):
        pCrawl = prev = self.root
        length = len(key)
        
        for i in range(length):
            if pCrawl.children[ord(key[i])-ord('a')] is None:
                return False
            prev = pCrawl
            pCrawl = pCrawl.children[ord(key[i])-ord('a')]
        
        return prev.children[ord(key[i])-ord('a')].eow
            

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        for key in words:
            self.trie.insert(key[::-1])
        
        self.word = ''
        

    def query(self, letter: str) -> bool:
        self.word = letter + self.word
        pCrawl = self.trie.root

        for c in self.word:
            if pCrawl.children[ord(c)-ord('a')] is not None:
                if pCrawl.children[ord(c)-ord('a')].eow:
                    return True
                pCrawl = pCrawl.children[ord(c)-ord('a')]
            else:
                return False
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = {}
        self.end = \"*\"
        self.q = deque()
        for word in words:
            self.insert(word[::-1])
    
    def insert(self, word):
        node = self.root
        for c in word:
            if c not in node: node[c] = {}
            node = node[c]
        node[self.end] = True

    def query(self, letter: str) -> bool:
        self.q.appendleft(letter)
        node = self.root
        for c in self.q:
            if self.end in node: return True
            if c not in node: return False
            
            node = node[c]
        return self.end in node


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Trie:
    def __init__(self):
        self.word = \"\"
        self.kids = dict()
        
class StreamChecker:
    
    
    def __init__(self, words: List[str]):
        self.root = Trie()
        def add(word):
            node = self.root
            for ch in word:
                if not node.kids.get(ch, None):
                    node.kids[ch] = Trie()
                node = node.kids[ch]
            node.word = word
        for word in words:
            add(word[::-1])
        self.stream = []
            

    def query(self, letter: str) -> bool:
        self.stream.append(letter)
        node = self.root
        for i in range(len(self.stream)-1, -1, -1):
            ch = self.stream[i]
            if not node.kids.get(ch, None):
                return False
            node = node.kids.get(ch)
            if node.word:
                return True
        return False
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Trie:
    def __init__(self):
        self.Trie = {}
        
    def insert(self, word):
        curr = self.Trie
        
        for i in word:
            if i not in curr:
                curr[i] = {}
            curr = curr[i]
        curr['#'] = 1
    
    def search(self, word):
        curr = self.Trie
        
        for i in word:
            if i not in curr:
                return False
            else:
                if '#' in curr[i]:
                    return True
            curr = curr[i]
        return False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.dictTree = Trie()
        self.queryStream = list()
        
        for i in words:
            self.dictTree.insert(i[::-1])
        

    def query(self, letter: str) -> bool:
        self.queryStream[0:0] = letter
        return self.dictTree.search (self.queryStream)
                
                
            
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.memo = {}
        self.words = set()
        for word in words:
            word_ = word[::-1]
            for i in range(len(word)):
                self.memo[word_[:i+1]]=0
            self.words.add(word_)        
        self.hist = []
        
        #print(self.memo)
    
    def query(self, letter: str) -> bool:
        self.hist.append(letter)
        w = ''
        for i in range(len(self.hist)-1,-1,-1):
            w+=self.hist[i]
            #print(w)
            if w in self.words:
                return True
            if w not in self.memo:
                return False
            
        return False



class TrieNode:
    
    def __init__(self, val  =   \"\"):
        self.val    =   val;
        self.next_chars =   collections.defaultdict(str);
        self.end_of_word    =   False;
        return;

class Trie:
    
    def __init__(self, words):
        self.head       =   TrieNode(\"head\");
        self.curr_ptr   =   self.head;
        
        for w in words:
            self._add_word(w);
            
        return;
    
    def check_char(self, c):
        ptr =   self.curr_ptr;
        
        if c not in ptr.next_chars:
            self.curr_ptr   =   self.head;
            if c in self.curr_ptr.next_chars:
                self.curr_ptr   =   self.head.next_chars[c];
            return False;
        
        self.curr_ptr   =   ptr.next_chars[c];
        return True;
    
    def ptr_end_of_word(self):
        return self.curr_ptr.end_of_word;
    
    def _add_word(self, word):
        
        ptr =   self.head;
        
        for c in word:
            
            if c not in ptr.next_chars:
                ptr.next_chars[c]   =   TrieNode(c);
            
            ptr =   ptr.next_chars[c];
        
        ptr.end_of_word =   True;
        
        return;

MAX_LENGTH  =   2001;

class StreamChecker:
    
    
    def __init__    (self, words):
        
        self.last_char_words    =   collections.defaultdict(set);
        self.rolling_word       =   \"\";
        
        for w in words:
            last_c  =   w[-1];
            self.last_char_words.setdefault(last_c, set()).add(w);
        
        #print(self.last_char_words);
        return;
    
    def query(  self, letter:str)   -> bool:
        
        self.rolling_word += letter;
        
        for w in self.last_char_words[letter]:
            ln_w    =   len(w);
            
            if self.rolling_word[-ln_w:] == w:
                return True;
        
        self.rolling_word   =   self.rolling_word[-MAX_LENGTH:];
        return False;
        

    \"\"\"
    def __init__(self, words: List[str]):
        
        self.trie_words =   Trie(words);      
        

    def query(self, letter: str) -> bool:
        
        ptr =   self.trie_words.curr_ptr;
  
        #print(letter, ptr.val, ptr.end_of_word);

        
        check_letter        =   self.trie_words.check_char(  letter);
        check_end_of_word   =   self.trie_words.ptr_end_of_word();
        
        #print(  letter, check_letter,   check_end_of_word);
        return  check_letter    and  check_end_of_word;

    \"\"\"
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

# class StreamChecker:

#     def __init__(self, words: List[str]):
#         if len(words) ==0:
#             print(\"Empty list!\")
#         elif len(words) > 2000:
#             print(\"List is too long!\")
#         max_word_len,  min_word_len = max([len(word) for word in words]), min([len(word) for word in words])
#         if min_word_len == 0:
#             print(\"Word is empty string!\")
#         elif max_word_len > 2000:
#             print(\"Word is too long!\")
#         words_dict = {}
#         for word in words:
#             k = len(word)
#             words_dict[k] = words_dict.get(k,[]) + [word]
#         self.sorted_words = sorted(words_dict.items())
#         self.queries = ''
#         self.n_queries = 0

#     def query(self, letter: str) -> bool:
#         self.queries += letter
#         self.n_queries += 1
#         if self.n_queries > 40000:
#             print(\"The number of queries is more than 40000!\")
#         for k_words in self.sorted_words:
#             k, words = k_words[0], k_words[1]
#             s = self.queries[(self.n_queries - k):self.n_queries]
#             for word in words:
#                 if word == s:
#                     return True
#         return False
class StreamChecker:

    def __init__(self, words: List[str]):
        self.s = ''
        self.dic = collections.defaultdict(set)
        for w in words:
            self.dic[w[-1]].add(w)
                

    def query(self, letter: str) -> bool:
        self.s += letter
        return any(self.s.endswith(w) for w in self.dic[letter])       

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    
    def __init__(self):
        self.child = {}
        self.end = False
    
    def insert(self, word):
        node = self
        idx = 0
        for char in word:
            if node.child.get(char) is None:
                node.child[char] = TrieNode()
            node = node.child[char]
        node.end = True
    
    def search(self, word):
        node = self
        for char in word:
            if node.child.get(char) is None:
                return False
            node = node.child[char]
            if node.end:
                return True
        return False
        
                
        

class StreamChecker:

    def __init__(self, words: List[str]):
        self.maxLen = max(map(len, words))
        self.trie = TrieNode()
        for word in words:
            self.trie.insert(\"\".join(list(word)[::-1]))
        self.curQuery = ''

    def query(self, letter: str) -> bool:
        self.curQuery = letter + self.curQuery[:min(len(self.curQuery), self.maxLen - 1)]
        return self.trie.search(self.curQuery)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Tri:
    def __init__(self):
        self.root = TriNode()
        
    def add(self, word):
        node = self.root
        
        for letter in word:
            if letter not in node.__next__:
                 node.next[letter] = TriNode()
               
            node = node.next[letter]
            
        node.isWord = True
        
    def check(self, letters):
        node = self.root
        
        for letter in letters:
            if node.isWord:
                return True
            
            if letter not in node.__next__:
                return False
            
            node = node.next[letter]
            
        if node.isWord:
            return True
            
        return False
        
            

class TriNode:
    def __init__(self):
        self.next = {}
        self.isWord = False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.tri = Tri()
        self.recent = []
        self.maxLength = -1
        self.length = 0
        
        for word in words:
            if len(word) > self.maxLength:
                maxLength = len(word)
                
            self.tri.add(word[::-1])
        

    def query(self, letter: str) -> bool:
        if self.length == self.maxLength:
            self.recent.pop()
            self.recent.insert(0, letter)
        else:
            self.recent.insert(0, letter)
            self.length += 1
            
        return self.tri.check(self.recent)
            
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.str = ''
        self.dict_set = collections.defaultdict(set)
        for word in words:
            self.dict_set[word[-1]].add(word)
        

    def query(self, letter: str) -> bool:
        self.str += letter
        return any(self.str.endswith(word) for word in self.dict_set[letter])
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        
        import collections
        
        self.trie = dict()
        self.maxLen = 0
        
        for word in words:
            node = self.trie
            self.maxLen = max(self.maxLen, len(word))
            for w in (word[::-1] + \"*\"):
                if w not in node:
                    node[w] = dict()
                node = node[w]
                
        self.queue = collections.deque([], self.maxLen)

    def query(self, letter: str) -> bool:
        
        self.queue.append(letter)
        term = list(self.queue)
        term = term[::-1] + [\"*\"]
        i = 0
        node = self.trie
        
        while(i<len(term)):
            if \"*\" in node:
                return(True)
            elif term[i] not in node:
                return(False)
            else:
                node = node[term[i]]
                i += 1
                
        return(True)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Trie:
    def __init__(self):
        self.root = {}
    
    def insert(self,word):
        node = self.root
        for ch in word:
            if ch not in node:
                node[ch] ={}
            node = node[ch]
        node[\"$\"] = True
    def search_word(self,prefix):
        node = self.root
        
        for letter in prefix:
            if letter in node:
                node = node[letter]
                if \"$\" in node:
                    return True
            else:
                return False
        return \"$\" in node

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        for word in words:
            self.trie.insert(word[::-1])
        self.cur_query = collections.deque()
        

    def query(self, letter: str) -> bool:
        self.cur_query.appendleft(letter)
        return self.trie.search_word(self.cur_query)
    
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

# class StreamChecker:

#     def __init__(self, words: List[str]):
#         # if len(words) ==0:
#         #     print(\"Empty list!\")
#         # elif len(words) > 2000:
#         #     print(\"List is too long!\")
#         # max_word_len,  min_word_len = max([len(word) for word in words]), min([len(word) for word in words])
#         # if min_word_len == 0:
#         #     print(\"Word is empty string!\")
#         # elif max_word_len > 2000:
#         #     print(\"Word is too long!\")
#         words_dict = {}
#         for word in words:
#             k = len(word)
#             words_dict[k] = words_dict.get(k,set())
#             words_dict[k].add(word)
#         self.sorted_words = sorted(words_dict.items())
#         self.queries = ''
#         self.n_queries = 0

#     def query(self, letter: str) -> bool:
#         self.queries += letter
#         self.n_queries += 1
#         # if self.n_queries > 40000:
#         #     print(\"The number of queries is more than 40000!\")
#         for k_words in self.sorted_words:
#             k, words = k_words[0], k_words[1]
#             s = self.queries[(self.n_queries - k):self.n_queries]
#             for word in words:
#                 if word == s:
#                     return True
#         return False
class StreamChecker:

    def __init__(self, words: List[str]):
        self.s = ''
        self.dic = collections.defaultdict(set)
        for w in words:
            self.dic[w[-1]].add(w)
                

    def query(self, letter: str) -> bool:
        self.s += letter
        return any(self.s.endswith(w) for w in self.dic[letter])       

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.letters = \"\"
        self.dict = collections.defaultdict(set)
        for i in words:
            self.dict[i[-1]].add(i)
            

    def query(self, letter: str) -> bool:
        self.letters += letter[0]
        return any(self.letters.endswith(word) for word in self.dict[letter])



# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self, val):
        self.val = val
        self.branches = dict()
    def query(self, word):
        \"\"\"
        returns true if and only if for some k >= 1, the last k characters of the string WORD is in the trie 
        \"\"\"
        # print(\"querying\", word)
        if \"*\" in self.branches:
            # print(\"found word\")
            return True
        if word and word[-1] in self.branches:
            return self.branches[word[-1]].query(word[:-1])
        return False
        
    def addWord(self, word):
        if not word:
            self.branches[\"*\"] = TrieNode('*')
        else:
            next_letter = word[-1]
            if next_letter not in self.branches:
                self.branches[next_letter] = TrieNode(next_letter)
            self.branches[next_letter].addWord(word[:-1])
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = TrieNode(\"head\")
        for w in words:
            self.trie.addWord(w)
        self.stream = \"\"

    def query(self, letter: str) -> bool:
        self.stream += letter
        return self.trie.query(self.stream)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.s = ''
        self.dict = collections.defaultdict(set)
        for word in words:
            self.dict[word[-1]].add(word)
        

    def query(self, letter: str) -> bool:
        self.s += letter
        return any(self.s.endswith(word) for word in self.dict[letter])
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    def __init__(self, c: str, is_word: bool):
        self.c = c
        self.next_chars = {}
        self.is_word = is_word 
    def traverse(self, c):
        if c in self.next_chars:
            return self.next_chars[c]
        return None

    def add(self, c, is_word):
        if c not in self.next_chars:
            self.next_chars[c] = Trie(c, is_word)
        return self.next_chars[c]
    
class StreamChecker:
            
    def __init__(self, words: List[str]):
        self.tr = Trie(\"\", False)
        self.iters = deque()
        self.longest_word = 0
        
        for word in words:
            self.longest_word = max(len(word), self.longest_word)
            cur = self.tr
            for c in word[::-1]:
                cur = cur.add(c, False)
            cur.is_word = True

    def query(self, letter: str) -> bool:
        self.iters.appendleft(letter)
        if len(self.iters) > self.longest_word:
            self.iters.pop()
        cur = self.tr
        for c in self.iters:
            cur = cur.traverse(c)
            if not cur:
                return False
            if cur.is_word:
                return True
            
        return False
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
    '''based on trie
       the core idea TLE is to create the trie with words in reverse order. also create a buffer that is used durring the query
    '''
    def __init__(self, words: List[str]):
        self.s = ''
        self.dic = defaultdict(set)
        for w in words:
            self.dic[w[-1]].add(w)

    def query(self, letter: str) -> bool:
        self.s += letter
        return any(self.s.endswith(w) for w in self.dic[letter])

class TrieNode:
    def __init__(self):
        self.children, self.end_node = {}, 0
         
class Trie:
    def __init__(self):
        self.root = TrieNode()

    def insert(self, word):
        root = self.root
        for symbol in word:
            root = root.children.setdefault(symbol, TrieNode())
        root.end_node = 1

class StreamChecker:
    def __init__(self, words):
        self.trie = Trie()
        self.Stream = deque()
        for word in words: self.trie.insert(word[::-1])
         
    def query(self, letter):
        self.Stream.appendleft(letter)
        cur = self.trie.root
        for c in self.Stream:
            if c in cur.children:
                cur = cur.children[c]
                if cur.end_node: return True
            else: break
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)
# put all our words to Trie in reversed order
# Imagine we have a current stream abcdefghij and we have dictionary [hij, xyz, abc, hijk] Then what we need to check if some suffix of this word in our dictinonary. It means that jihgfedcba should have jih as prefix. If we add one letter to strim, so we have abcdefghijk, we need to find prefixes in kjihgfedcba and so on.

# Code:

# 1)Trie class with initialization and insert function. Each node has children and flag .end_node, which says if some word ends with this node.
# 2)Put all reversed words to our Trie
# 3)For each new element of stream, we keep it in deque, so we can easily add it to the left of our reversed stream. Then we traverse our Trie and look if we reached some end node.

# Complexity: Let m be the longest length of word and n be number of words. Also let w be number of query(letter). Then space complexity is O(mn + w) to keep our tree. In fact we can cut our deque if it has length more than m, because we never reach nodes which are far in our deque. Time complexity is O(wm), because for each of w queries we need to traverse at most m letters in our trie.

# Note that other method complexity I mentioned in the beginning in theory is also O(wm), but in practise it works like 10 times slower. The problem is with tests like aaaaaa...aaab.
# see DBabichev's explanation. https://leetcode.com/problems/stream-of-characters/discuss/807541/Python-Trie-with-reversed-words-explained


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.stream = deque([])
        
        for word in set(words):
            node = self.trie
            for char in reversed(word):
                if not char in node:
                    node[char] = {}
                node = node[char]
            node['!'] = word
        
    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        
        node = self.trie
        for char in self.stream:
            if '!' in node:
                return True
            if not char in node:
                return False
            node = node[char]
        return '!' in node


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie={}
        self.stream=collections.deque()
        for word in words:
            node=self.trie
            for ch in word[::-1]:
                if not ch in node:
                    node[ch]={}
                node=node[ch]
            node['$']=word
        

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        node=self.trie
        for c in self.stream:
            if '$' in node:
                return True
            if not c in  node:
                return False
            node=node[c]
        #print('$' in node)
        return '$' in node


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)



class StreamChecker:
    def __init__(self, words: List[str]):
        self.s = ''
        self.dic = collections.defaultdict(set)
        for w in words:
            self.dic[w[-1]].add(w)
                

    def query(self, letter: str) -> bool:
        self.s += letter
        return any(self.s.endswith(w) for w in self.dic[letter])

class StreamChecker:

    def __init__(self, words: List[str]):
        self.queried_word = \"\"
        self.dict_sets = defaultdict(lambda: set())
        for word in words:
            self.dict_sets[word[-1]].add(word)

    def query(self, letter: str) -> bool:
        self.queried_word += letter
        for word in self.dict_sets[letter]:
            if word == self.queried_word[-len(word):]:
                return True
        return False

class Trie:
    #GOOGLE, FB
    #Am I checking for \"cd\" or \"dc\" as well in [\"cd\",\"f\",\"kl\"] ?
    def __init__(self):
        self.endOfWord = None
        self.children = [None]*26
    
    def insert(self, s):
        t = self #!!!!!!!!!!!!!!!!!!
        for c in s:
            if t.children[ord(c) - ord('a')] == None:
                t.children[ord(c) - ord('a')] = Trie()
            t = t.children[ord(c)-ord('a')]
        t.endOfWord = True
        
    def search(self, s):
        t = self
        for c in s:
            if t.children[ord(c) - ord('a')] == None: return False
            t = t.children[ord(c) - ord('a')]
            if t.endOfWord: return True
        return False

    
class StreamChecker:
    
    def __init__(self, words: List[str]):
        self.t = Trie()
        self.stream = collections.deque()
        for w in words:
            self.t.insert(reversed(w))
    
    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        return self.t.search(self.stream)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.children = collections.defaultdict(TrieNode)
        self.val = -1

class Trie:

    def __init__(self):
        self.root = TrieNode()

    def insert(self, word):

        current = self.root
        for char in word:
            current = current.children[char]

        current.val = 10
    def search(self, word):
        current = self.root
        for char in word:
            current = current.children.get(char)
            if not current:
                return False
        return current.val > 1
    def starts_with(self, word):
        current = self.root
        for char in word:
            current = current.children.get(char)
            if not current:
                return False
        return True
    

class StreamChecker:

    # O(NW) where N is number of words
    # Q is maxlength of word
    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.letters = []
        for word in words:
            # insert in reverse order to check for Trie keys as soon as new node is added
            self.trie.insert(word[::-1])

    #waiting.size <= W, where W is the maximum length of words.
    # So that O(query) = O(waiting.size) = O(W)
    # for q queries, O(QW)
    def query(self, letter: str) -> bool:
        self.letters += letter
        i = len(self.letters) - 1
        node = self.trie.root
        curr_word = ''
        for i in range(len(self.letters) - 1, -1, -1):
            curr_word += self.letters[i]
            has_sub_word = self.trie.starts_with(curr_word)
            if not has_sub_word:
                return False
            if has_sub_word and self.trie.search(curr_word):
                return True
        return False
#         while i >= 0:
#             # if any of the word matches return True
#             if node.val > 1:
#                 return True
#             if self.letters[i] not in node.children:
#                 return False
#             node = node.children[self.letters[i]]
#             i -= 1
        
#         return node.val > 1
    




class Node:
    def __init__(self, end=False):
        self.end = end
        self.children = [None] * 26
        
    def search(self, word):
        curr = self
        for w in word:
            slot = ord(w) - ord('a')
            if curr.children[slot]:
                curr = curr.children[slot]
                if curr.end:
                    return True
            else:
                return False
        return curr.end

class StreamChecker:
            
    def __init__(self, words: List[str]):
        self.letters = ''
        self.root = Node('')
        def add(node, word):
            for w in word:
                slot = ord(w) - ord('a')
                if node.children[slot] is None:
                    node.children[slot] = Node()
                node = node.children[slot]
            node.end = True
                
        for word in words:
            add(self.root, word[::-1])

    def query(self, letter: str) -> bool:
        self.letters = letter + self.letters
        return self.root.search(self.letters)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self, char):
        self.node = char
        self.children = {}
        self.end_word = False


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = TrieNode('*')
        for word in words:
            curr_node = self.trie
            for char in word[::-1]:
                node = curr_node.children.get(char, TrieNode(char))
                curr_node.children[char] = node
                curr_node = node
            curr_node.end_word = True
        self.queried = ''
    
    def exists(self, word):
        #dc
        curr_node = self.trie
        for char in word:
            if char not in curr_node.children:
                return False
            curr_node = curr_node.children[char]
            if curr_node.end_word:
                return True
        if curr_node.end_word:
            return True
        return False

    def query(self, letter: str) -> bool:
        root = self.trie
        self.queried = letter + self.queried
        if self.exists(self.queried):
            return True
        return False
        
'''
 * (d->c->e, f, l->k)


[a,b,c,]


1. checking the actual problem
2. checking the trie
'''        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self, char):
        self.char = char
        self.accept = False
        self.children = {}

class StreamNode:
    def __init__(self, char):
        self.char = char
        self.next = None

class StreamChecker:

    def __init__(self, words: List[str]):
        self.maxlen = 0
        self.trie = TrieNode(\"\")
        i = 0
        should_continue = True
        for j in range(len(words)):
            word = words[j]
            self.maxlen = max(len(word), self.maxlen)
            p = self.trie
            for i in range(len(word)-1,-1,-1):
                c = word[i]
                if c not in p.children:
                    p.children[c] = TrieNode(c)
                p = p.children[c]
                p.accept = p.accept or (i == 0)
        self.stream = None

    def query(self, letter: str) -> bool:
        s = StreamNode(letter)
        s.next = self.stream
        self.stream = s
        p = self.trie
        i = 0
        accept = False
        while s != None and i < self.maxlen:
            if s.char not in p.children:
                return False
            p = p.children[s.char]
            if p.accept:
                return True
            s = s.next
            i += 1
        return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.memo = {}
        self.words = set()
        words_ = [word[::-1] for word in words]
        for word in words_:
            for i in range(len(word)-1):
                self.memo[word[:i+1]]=0
        
        self.max_len = 0
        for word in words_:
            self.memo[word]=1
        
        self.hist = []
        
        #print(self.memo)
    
    def query(self, letter: str) -> bool:
        self.hist.append(letter)
        w = ''
        for i in range(len(self.hist)-1,-1,-1):
            w+=self.hist[i]
            #print(w)
            c = self.memo.get(w,None)
            if c is None:
                return False
            if c:
                return True
            
        return False



class Trie:
    
    def __init__(self):
        self.endOfWord = False
        self.children = [None]*26

    def insert(self, s):
        t = self
        for c in s:
            if t.children[ord(c)-ord('a')] == None:
                t.children[ord(c)-ord('a')] = Trie()
            t = t.children[ord(c)-ord('a')]
        t.endOfWord = True

    def search(self, s):
        t = self
        for c in s:
            if t.children[ord(c)-ord('a')] == None: return False
            t = t.children[ord(c)-ord('a')]
            if t.endOfWord: return True
        return False


class StreamChecker:

    def __init__(self, words: List[str]):
        self.t = Trie()
        self.stream = collections.deque()
        for w in words:
            self.t.insert(reversed(w))

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        return self.t.search(self.stream)
        


# 1032. Stream of Characters

# class TrieNode:
#     def __init__(self, val=None, isEnd=False):
#         self.val = val
#         self.isEnd = isEnd
#         self.next = {}

# Solution 4: Construct Trie with Reversed Words
# Time: 600 ~ 700ms, Time complexity: O(WQ)

import functools 

class StreamChecker:
    
    def __init__(self, words):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in words: 
            functools.reduce(dict.__getitem__, w[::-1], self.trie)['#'] = True
            # print(self.trie)
        self.S = \"\"
        self.W = max(map(len, words))

    def query(self, letter):
        self.S = (letter + self.S)[:self.W]
        cur = self.trie
        for c in self.S:
            if c in cur:
                cur = cur[c]
                if cur['#'] == True:
                    return True
            else:
                break
        return False

# class StreamChecker:

#     def __init__(self, words: List[str]):
#         self.trie = {}
#         self.stream = deque([])

#         for word in set(words):
#             node = self.trie       
#             for ch in word[::-1]:
#                 if not ch in node:
#                     node[ch] = {}
#                 node = node[ch]
#             node['$'] = word
        
        
#     def query(self, letter: str) -> bool:
#         self.stream.appendleft(letter)
        
#         node = self.trie
#         for ch in self.stream:
#             if '$' in node:
#                 return True
#             if not ch in node:
#                 return False
#             node = node[ch]
#         return '$' in node
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self):
        self.children = {}
        self.isLeaf = False
        
    def add(self, word) -> None:
        if not word:
            return
        first = word[0]
        if first not in self.children:
            self.children[first] = TrieNode()
        if len(word) == 1:
            self.children[first].isLeaf = True
        self.children[first].add(word[1:])
        
    def search(self, word) -> bool:
        if not word:
            return self.isLeaf   
        first = word[0]
        if first not in self.children:
            return False
        return self.children[first].search(word[1:])
    

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trieRoot = TrieNode()
        for word in words:
            self.trieRoot.add(word[::-1])
        self.stream = []
        
    def query(self, letter: str) -> bool:
        self.stream.append(letter)
        node = self.trieRoot
        for ch in reversed(self.stream):
            if ch in node.children:
                node = node.children[ch]
                if node.isLeaf:
                    return True
            else:
                break
                
        return False
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie={}
        self.searchWord=''
        for word in words:
            word=word[::-1]
            self.insertToTrie(self.trie, word)
            
    def insertToTrie(self, trie, word):
        if word[0] not in trie:
            trie[word[0]] = {\"value\":{}, \"isLast\":len(word)==1}
        if len(word)==1:
            trie[word[0]][\"isLast\"] = True
            return
        self.insertToTrie(trie[word[0]][\"value\"], word[1:])
            
    def searchForWord(self, trie, word):
        if not word or word[0] not in trie:
            return False
        if trie[word[0]][\"isLast\"]:
            return True
        return self.searchForWord(trie[word[0]][\"value\"], word[1:])

    def query(self, letter: str) -> bool:
        self.searchWord = letter + self.searchWord
        result = self.searchForWord(self.trie, self.searchWord)
        return result


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Node :
    def __init__(self) :
        self.child = [None] * 26
        self.w = False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = Node()
        for w in words :
            p = self.root
            for ch in w[::-1] :
                k = ord(ch) - ord('a')
                if not p.child[k] :
                    p.child[k] = Node()
                p = p.child[k]
            p.w = True
        
        self.q = []

    def query(self, letter: str) -> bool:
        self.q.append(letter)
        p = self.root
        for i in range(len(self.q)-1, -1, -1):
            k = ord(self.q[i]) - ord('a')
            if not p.child[k] :
                return False
            p = p.child[k]
            if p.w :
                return True
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie={}
        
        for word in set(words):
            node=self.trie
            for c in word[::-1]:
                node=node.setdefault(c,{})
            node['$']=word
        self.nodelist=[]
    def query(self, letter: str) -> bool:
        self.nodelist.insert(0,letter)
    
        node = self.trie
        for ch in self.nodelist:
            if '$' in node:
                return True
            if not ch in node:
                return False
            node = node[ch]
        return '$' in node


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.children = [None]*26
        self.isEnd = False
    

class StreamChecker:

    def __init__(self, words: List[str]):
        self.s = []
        self.root = TrieNode()
        for w in words:
            # self.insert(self.root,w)
            node = self.root
            for i in range(len(w)-1,-1,-1):
                idx = ord(w[i]) - ord('a')
                if not node.children[idx]:
                    node.children[idx] = TrieNode()
                node = node.children[idx]
            node.isEnd = True
        

    def query(self, letter: str) -> bool:
        self.s.append(letter)
        node = self.root
        for i in range(len(self.s)-1,-1,-1):
            idx = ord(self.s[i]) - ord('a')
            node = node.children[idx]  
            if node != None and node.isEnd:
                return True
            if node == None:
                return False
              
        # print(self.root.children)
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.children = [None]*26
        self.end = False

class StreamChecker:
    
    def __init__(self, words: List[str]):
        self.root = TrieNode()
        for word in words:
            node = self.root
            for ch in word[::-1]:
                ind = ord(ch) - ord('a')
                if node.children[ind] is None:
                    node.children[ind] = TrieNode()
                node = node.children[ind]
            node.end = True
        self.hist = ''

    def query(self, letter: str) -> bool:
        self.hist = letter + self.hist
        node = self.root
        for ch in self.hist:
            ind = ord(ch) - ord('a')
            if node.children[ind] is None:
                return False
            node = node.children[ind]
            if node.end:
                return True
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
    letter_queue = \"\"
    def __init__(self, words: List[str]):
        self.words_dict = {}
        for w in words:
            if w[-1] in self.words_dict:
                self.words_dict[w[-1]].add(w)
            else:
                self.words_dict[w[-1]] = set()
                self.words_dict[w[-1]].add(w)
        
    def query(self, letter: str) -> bool:
        self.letter_queue += letter
        if letter in self.words_dict:
            for item in self.words_dict[letter]:
                if item == self.letter_queue[-len(item):]: return True
     
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self):
        self.children = {}
        self.terminal = False
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = TrieNode()
        self.history = []
        for word in words:
            node = self.root
            for char in word[::-1]:
                if char not in node.children:
                    node.children[char] = TrieNode()
                node = node.children[char]
            node.terminal = True
        
        
    def query(self, letter: str) -> bool:
        self.history.append(letter)
        node = self.root
        for i in reversed(list(range(len(self.history)))):
            if self.history[i] in node.children:
                node = node.children[self.history[i]]
                if node.terminal: return True
            else:
                return False
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
    class Trie:
        def __init__(self):
            self.next = {}
            self.ending = False
            
        def add(self,s):
            if s != \"\":
                if s[0] not in self.next:
                    self.next[s[0]] = StreamChecker.Trie()
                self.next[s[0]].add(s[1:])
            else:
                self.ending = True
                
        def __contains__(self,s):
            if self.ending:
                return True
            elif s == \"\":
                return False
            elif s[-1] in self.next:
                return self.next[s[-1]].__contains__(s[:len(s)-1])
            else:
                return False
            
    def __init__(self, words: List[str]):
        self.words = self.Trie()
        for w in words: self.words.add(w[::-1])
        self.q = \"\"

    def query(self, letter: str) -> bool:
        self.q += letter
        return self.q in self.words

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Node:

    def __init__(self):
        self.edges = {}
        
    def hasEdge(self, edge):
        return edge in self.edges
    
    def getEdge(self, edge):
        return self.edges[edge]
    
    def addEdge(self, edge):
        if not self.hasEdge(edge):
            self.edges[edge] = Node()
    
    def isEnd(self):
        return \"*\" in self.edges
    
class Trie:
    
    def __init__(self):
        self.root = Node()
    
    def addWord(self, word):
        node = self.root
        
        for c in word:
            if not node.hasEdge(c):
                node.addEdge(c)   
            node = node.getEdge(c)
            
        node.addEdge(\"*\")
        
    def search(self, stream):
        node = self.root
        
        for c in stream:
            if not node.hasEdge(c):
                return False
            
            node = node.getEdge(c)
            
            if node.hasEdge(\"*\"):
                return True
        
        return False
    
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.stream = collections.deque()
        
        for word in words:
            self.trie.addWord(word[::-1])

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        return self.trie.search(self.stream)

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)



class StreamChecker:

    def __init__(self, words: List[str]):
        self.words = set(words)
        self.max_len = max((len(x) for x in self.words), default=0)
        self.q = ''
        self.num_end = min(1, self.max_len)
        self.ends = {}
        for i in range(1, self.num_end + 1):
            self.ends[i] = set(x[-i:] for x in self.words if len(x) >= i)
        # print(self.ends)
        

    def query(self, letter: str) -> bool:
        self.q += letter
        if len(self.q) > self.max_len:
            self.q = self.q[1:]
        for i in range(1, self.num_end + 1):
            # print(i, self.q[-i:])
            if self.q[-i:] not in self.ends[i]:
                return False
        # print('cont', i, self.q)
        for i in range(0, self.max_len):
            # print(~i, self.q[~i:])
            if self.q[~i:] in self.words:
                # print(self.q[~i:])
                return True
        return False
        

# Standard solution for string match is Trie.
class StreamChecker(object):

    def __init__(self, words):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in words:
            reduce(dict.__getitem__, w, self.trie)['#'] = True
        self.waiting = []

    def query(self, letter):
        self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any(\"#\" in node for node in self.waiting)        


# more readable Trie
class StreamChecker(object):

    def __init__(self, words):
        self.trie = {}
        self.query_letters = []        
        for word in words:
            node = self.trie
            for c in reversed(word):
                if c not in node:
                    node[c] = {}
                node = node[c]
            node['END'] = True
            
    def query(self, letter):
        self.query_letters.append(letter)
        node = self.trie
        for c in reversed(self.query_letters):
            if c in node:
                node = node[c]
                if 'END' in node:
                    return True
            else:
                return False
        return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

from collections import deque

class TrieNode:
    def __init__(self, val):
        # self.val = val
        self.end = False
        self.children = {}
        
class Trie:
    
    def __init__(self):
        self.root = TrieNode(-1)
    
    def add(self, word):
        root = self.root
        for idx, ch in enumerate(word):
            children = root.children
            if children.get(ch) == None:
                child = TrieNode(ch)
                children[ch] = child
                root = child
            else:
                root = children[ch]
                
            if idx == len(word)-1:
                root.end = True
    
    def search(self, word):

        root = self.root
        for idx, val in enumerate(word):
            if root.children.get(val) == None:
                return False
            else:
                root = root.children[val]
                if root.end:
                    return True
            # if idx == len(word)-1 and root.end:
            #     return True
        
class StreamChecker:

    def __init__(self, words: List[str]):
        # self.words = set(words)
        self.Trie = Trie()
        self.maxlen = -1
        for w in words:
            # add word to Trie
            self.maxlen = max(self.maxlen, len(w))
            rev = w[::-1]
            self.Trie.add(rev)
        self.searchArr = deque()
        

    def query(self, letter: str) -> bool:

        self.searchArr.insert(0, letter)
        if len(self.searchArr) > self.maxlen:
            self.searchArr.pop()

        tmpWord = \"\".join(self.searchArr)    
        if self.Trie.search(tmpWord):
            return True        

        return False    
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

from collections import deque

class TrieNode:
    def __init__(self, val):
        self.end = False
        self.children = {}
        
class Trie:
    
    def __init__(self):
        self.root = TrieNode(-1)
    
    def add(self, word):
        root = self.root
        for ch in word:
            children = root.children
            if children.get(ch) == None:
                child = TrieNode(ch)
                children[ch] = child
                root = child
            else:
                root = children[ch]

        root.end = True
    
    def search(self, word):

        root = self.root
        for idx, val in enumerate(word):
            if root.children.get(val) == None:
                return False
            else:
                root = root.children[val]
                if root.end:
                    return True
        
class StreamChecker:

    def __init__(self, words: List[str]):
        # self.words = set(words)
        self.Trie = Trie()
        self.maxlen = -1
        for w in words:
            self.maxlen = max(self.maxlen, len(w))
            rev = w[::-1]
            self.Trie.add(rev)
        self.searchArr = deque()
        

    def query(self, letter: str) -> bool:

        self.searchArr.insert(0, letter)
        if len(self.searchArr) > self.maxlen:
            self.searchArr.pop()

        tmpWord = \"\".join(self.searchArr)    
        return self.Trie.search(tmpWord)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Trie:
    def __init__(self):
        self.endofword = False
        self.children = [None] * 26
        
    def insert(self, s):
        t = self
        for c in s:
            if t.children[ord(c) - ord('a')] == None:
                t.children[ord(c) - ord('a')] = Trie()
            t = t.children[ord(c) - ord('a')]
        t.endofword = True

    def search(self, s):
        t = self
        for c in s:
            if t.children[ord(c)-ord('a')] == None: return False
            t = t.children[ord(c)-ord('a')]
            if t.endofword == True: return True
        return False
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.t = Trie()
        self.stream = collections.deque()
        
        for w in words:
            self.t.insert(reversed(w))

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        return self.t.search(self.stream)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TNode(object):
    def __init__(self):
        self.d,self.f = {}, False
class StreamChecker(object):
    def __init__(self, words):
        self.root = TNode()
        self.max_ = max(map(len, words))
        for w in words:
            cur = self.root
            for j in range(len(w)-1,-1,-1):
                if w[j] not in cur.d: cur.d[w[j]] = TNode()
                cur = cur.d[w[j]]
            cur.f = True
        self.q = collections.deque([])        

    def query(self, letter):
        self.q.appendleft(letter)
        if len(self.q) > self.max_: self.q.pop()
        cur= self.root
        for l in self.q:
            if l not in cur.d: return False
            cur = cur.d[l]
            if cur.f:
                return True
        return False

class TrieNode:
    def __init__(self):
        self.children = {}
        self.end = 0
class Trie:
    def __init__(self):
        self.root = TrieNode()
    def insert(self,word):
        root = self.root
        for char in word:
            root = root.children.setdefault(char,TrieNode())
        root.end=1
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.Trie = Trie()
        self.QueryBuffer = deque()
        for word in words:
            self.Trie.insert(word[::-1])

    def query(self, letter: str) -> bool:
        self.QueryBuffer.appendleft(letter)
        cur = self.Trie.root
        for char in self.QueryBuffer:
            if char in cur.children:
                cur = cur.children[char]
                if cur.end==1:
                    return True
            else:
                break
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.children = [None]*26
        self.isEnd = False
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = self.getNode()
        for word in words:
            self.addWord(word[::-1])
        self.currStr = deque([])
    
    def addWord(self, word):
        node = self.root
        for c in word:
            ind = self.getInd(c)
            if node.children[ind] == None:
                node.children[ind] = self.getNode()
            node = node.children[ind]
        node.isEnd = True
        
    def getInd(self, c):
        return ord(c)-ord('a')
    
    def getNode(self):
        return TrieNode()
    
    def findWord(self, letter):
        self.currStr.appendleft(letter)
        
        node = self.root
        for ch in self.currStr:
            ind = self.getInd(ch)
            if node.children[ind] == None:
                return False
            elif node.children[ind].isEnd:
                return True
            node = node.children[ind]
        
        return node and node.isEnd
            
    
    def query(self, letter: str) -> bool:
        return self.findWord(letter)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


#Approach: Insert reversed words to the Trie. Also use a deque to store current stream, that way you know you're looking at the last character every time you get a new letter in the stream.

class TrieNode:
    def __init__(self):
        self.children = [None]*26
        self.isEnd = False
        
class StreamChecker:
    
    def __init__(self, words: List[str]):
        self.root = self.getNode()
        self.currStr = deque([])
        for word in words:
            self.addWord(word[::-1])
        
    def getNode(self):
        return TrieNode()
    
    def getInd(self, c):
        return ord(c) - ord('a')
    
    def addWord(self, word):
        node = self.root
        for ch in word:
            ind = self.getInd(ch)
            if node.children[ind] == None:
                node.children[ind] = self.getNode()
            node = node.children[ind]
        node.isEnd = True

    def query(self, letter: str) -> bool:
        self.currStr.appendleft(letter)
        
        node = self.root
        for ch in self.currStr:
            ind = self.getInd(ch)
            if node.children[ind] == None:
                return False
            elif node.children[ind].isEnd:
                return True
            node = node.children[ind]
        return node and node.isEnd


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    def __init__(self):
        self.end_word=False
        self.letters=[None]*26 #as there are 26 alphabets
        
    def insert(self, s):
        t=self
        for c in s:
            if t.letters[ord(c)-ord('a')]==None:
                t.letters[ord(c)-ord('a')]=Trie()
            t=t.letters[ord(c)-ord('a')]
        t.end_word=True
        
    def search(self, s):
        t=self
        for c in s:
            if t.letters[ord(c)-ord('a')]==None: return False
            t=t.letters[ord(c)-ord('a')]
            if t.end_word: return True
        return False




class StreamChecker:

    def __init__(self, words: List[str]):
        self.t=Trie()
        self.stream=collections.deque()
        for w in words:
            self.t.insert(reversed(w))
        

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        return self.t.search(self.stream)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


# 1032. Stream of Characters

# class TrieNode:
#     def __init__(self, val=None, isEnd=False):
#         self.val = val
#         self.isEnd = isEnd
#         self.next = {}

# Solution 4: Construct Trie with Reversed Words
# Time: 600 ~ 700ms
# Time complexity: O(WQ)

# Python
class StreamChecker:
    
    def __init__(self, words):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in words: reduce(dict.__getitem__, w[::-1], self.trie)['#'] = True
        self.S = \"\"
        self.W = max(map(len, words))

    def query(self, letter):
        self.S = (letter + self.S)[:self.W]
        cur = self.trie
        for c in self.S:
            if c in cur:
                cur = cur[c]
                if cur['#'] == True:
                    return True
            else:
                break
        return False

# class StreamChecker:

#     def __init__(self, words: List[str]):
#         self.trie = {}
#         self.stream = deque([])

#         for word in set(words):
#             node = self.trie       
#             for ch in word[::-1]:
#                 if not ch in node:
#                     node[ch] = {}
#                 node = node[ch]
#             node['$'] = word
        
        
#     def query(self, letter: str) -> bool:
#         self.stream.appendleft(letter)
        
#         node = self.trie
#         for ch in self.stream:
#             if '$' in node:
#                 return True
#             if not ch in node:
#                 return False
#             node = node[ch]
#         return '$' in node
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self):
        self.children = [None] * 26
        self.isEndOfWord = False
        
class Trie:
    def __init__(self):
        self.root = self.getNode()
        
    def getNode(self):
        return TrieNode()
    
    def charToIndex(self, c):
        return ord('a') - ord(c)
    
    def insert(self, word):
        start = self.root
        n = len(word)
        for i in range(n):
            idx = self.charToIndex(word[i])
            if not start.children[idx]:
                start.children[idx] = TrieNode()
            start = start.children[idx]
        start.isEndOfWord = True
    
    def search(self, word):
        start = self.root
        n = len(word)
        for i in range(n):
            idx = self.charToIndex(word[i])
            if start.children[idx] == None:
                return False
            start = start.children[idx]
            if start.isEndOfWord:
                return True
        return False

class StreamChecker:
    def __init__(self, words: List[str]):
        self.t = Trie()
        for word in words:
            self.t.insert(word[::-1])
        self.stream = collections.deque()
        

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        return self.t.search(self.stream)
        
            
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    def __init__(self, letter):
        self.next_letters = dict()
        self.letter = letter
        self.is_end_word = False
    def add_word(self, word, idx):
        if idx == -1:
            self.is_end_word = True
            return
        if word[idx] not in self.next_letters:
            self.next_letters[word[idx]] = Trie(word[idx])
        self.next_letters[word[idx]].add_word(word, idx-1)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie('')
        for w in words:
            self.trie.add_word(w, len(w)-1)
        self.history = list()

    def query(self, letter: str) -> bool:
        self.history.append(letter)
        cur_node = self.trie
        idx = len(self.history) - 1
        while idx >= 0 and self.history[idx] in cur_node.next_letters:
            c = self.history[idx]
            cur_node = cur_node.next_letters[c]
            if cur_node.is_end_word:
                return True
            idx -= 1
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.s = ''
        self.dic = collections.defaultdict(set)
        for w in words:
            self.dic[w[-1]].add(w)
                

    def query(self, letter: str) -> bool:
        self.s += letter
        return any(self.s.endswith(w) for w in self.dic[letter])


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.tab = collections.defaultdict(set)
        for w in words:
            self.tab[w[-1]].add(w[::-1])
            
        self.queried = ''
        

    def query(self, letter: str) -> bool:
        self.queried = letter + self.queried
        if letter not in self.tab:
            return False
        candidates = self.tab[letter]
        for can in candidates:
            if can == self.queried[:len(can)]:
                return True
        return False
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    def __init__(self, is_leaf):
        \"\"\"
        { element : {val : 1, is_end: False}]}

       \"\"\"
        self.is_leaf = is_leaf
        self.child = {}


class StreamChecker:

    def __init__(self, words: List[str]):
        # print(\"its here\")
        self.trie = {}
        self.max_length = 0
        self.word = \"\"
        for word in words:
            self.max_length = len(word) if len(word) > self.max_length else self.max_length
            self.insert_word(word)

    def query(self, letter: str) -> bool:
        self.word += letter
        self.word = self.word[-self.max_length:] if len(self.word) > self.max_length else self.word
        ans = self.search_word()
        return ans

    def insert_word(self, word):
        head = self.trie
        for i in range(len(word) - 1, -1, -1):
            if word[i] not in head:
                t = Trie(True) if i == 0 else Trie(False)
                head[word[i]] = t
                head = t.child
            else:
                node = head.get(word[i])
                if i == 0:
                    node.is_leaf = True
                head = node.child
                
                # print(head)

                
    def search_word(self):
        # print(\"searching \", self.word)
        head = self.trie
        # print(head)
        node = None
        for i in range(len(self.word) - 1, -1, -1):
            # print(\"letter \", self.word[i])
            if self.word[i] in head:
                node = head.get(self.word[i])
                head = node.child
                if node.is_leaf:
                    return True
            else:
                return False
        return node.is_leaf

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:
    def __init__(self, words: List[str]):
        self.dic = collections.defaultdict(set)
        self.s = ''
        for w in words:
            self.dic[w[-1]].add(w)
    def query(self, letter: str) -> bool:
        self.s += letter
        return any(self.s.endswith(w) for w in self.dic[letter])
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.s_list = []
        self.word_len = 0
        for w in words:
            tmp = self.trie
            for c in w[::-1]:
                tmp = tmp.setdefault(c, {})
            tmp['#'] = True
            self.word_len = max(self.word_len, len(w))

    def query(self, letter: str) -> bool:
        self.s_list += letter,
        self.s_list = self.s_list[-self.word_len:]
        curr = self.trie
        for c in self.s_list[::-1]:
            if c in curr:
                curr = curr[c]
                if curr.get('#', False):
                    return True
            else:
                break
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


import collections

class Trie:
    
    def __init__(self):
        self.children = [None] * 26
        self.is_end = False
        
    def insert(self, s):
        root = self
        for c in s:
            if root.children[ord(c) - ord('a')] is None:
                root.children[ord(c) - ord('a')] = Trie()
            root = root.children[ord(c) - ord('a')]
        root.is_end = True      
        
    def search(self, s):
        root = self
        for c in s:
            if root.children[ord(c) - ord('a')] is None:
                return False
            root = root.children[ord(c) - ord('a')] 
            if root.is_end:
                return True
        return False
    
class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = Trie()
        self.stream = collections.deque()
        for w in words:
            self.root.insert(reversed(w))        

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        return self.root.search(self.stream)
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.children, self.end_node = {}, 0
         
class Trie:
    def __init__(self):
        self.root = TrieNode()

    def insert(self, word):
        root = self.root
        for symbol in word:
            root = root.children.setdefault(symbol, TrieNode())
        root.end_node = 1

class StreamChecker:
    def __init__(self, words):
        self.trie = Trie()
        self.Stream = deque()
        for word in words: self.trie.insert(word[::-1])
         
    def query(self, letter):
        self.Stream.appendleft(letter)
        cur = self.trie.root
        for c in self.Stream:
            if c in cur.children:
                cur = cur.children[c]
                if cur.end_node: return True
            else: break
        return False


from collections import deque
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.max_word_len = 0
        for word in words:
            node = self.trie
            for i in reversed(list(range(len(word)))):
                if word[i] not in node:
                    node[word[i]] = {}
                node = node[word[i]]
            node[True] = True
            self.max_word_len = max(self.max_word_len, len(word))
        self.queue = deque()
            

            
    def query(self, letter: str) -> bool:
        self.queue.appendleft(letter)
        if len(self.queue) > self.max_word_len:
            self.queue.pop()
            
        node = self.trie
        for char in self.queue:
            if True in node:
                return True
            if char not in node:
                return False
            node = node[char]
        return True in node

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)



class TrieNode:
    def __init__(self):
        self.children = {}
        self.end_node = 0
         
class Trie:
    def __init__(self):
        self.root = TrieNode()

    def insert(self, word):
        root = self.root
        for symbol in word:
            root = root.children.setdefault(symbol, TrieNode())
        root.end_node = 1

        
class StreamChecker:
    def __init__(self, words):
        self.trie = Trie()
        self.Stream = deque()
        for word in words:
            self.trie.insert(word[::-1])
         
    def query(self, letter):
        self.Stream.appendleft(letter)
        cur = self.trie.root
        
        for c in self.Stream:
            if c in cur.children:
                cur = cur.children[c]
                if cur.end_node:
                    return True
            else:
                break
        return False

class StreamChecker:
    class Trie:
        def __init__(self):
            self.next = {}
            self.ending = False
            
        def add(self,s):
            if s != \"\":
                if s[-1] not in self.next:
                    self.next[s[-1]] = StreamChecker.Trie()
                self.next[s[-1]].add(s[:len(s)-1])
            else:
                self.ending = True
                
        def __contains__(self,s):
            if self.ending:
                return True
            elif s == \"\":
                return False
            elif s[-1] in self.next:
                return self.next[s[-1]].__contains__(s[:len(s)-1])
            else:
                return False
            
    def __init__(self, words: List[str]):
        self.words = self.Trie()
        for w in words: self.words.add(w)
        self.q = \"\"

    def query(self, letter: str) -> bool:
        self.q += letter
        return self.q in self.words

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

from collections import deque

class TrieNode:
    def __init__(self, val):
        # self.val = val
        self.end = False
        self.children = {}
        
class Trie:
    
    def __init__(self):
        self.root = TrieNode(-1)
    
    def add(self, word):
        root = self.root
        for idx, ch in enumerate(word):
            children = root.children
            if children.get(ch) == None:
                child = TrieNode(ch)
                children[ch] = child
                root = child
            else:
                root = children[ch]
                
            if idx == len(word)-1:
                root.end = True
    
    def search(self, word):

        root = self.root
        for idx, val in enumerate(word):
            if root.children.get(val) == None:
                return False
            else:
                root = root.children[val]
                if root.end:
                    return True
        
class StreamChecker:

    def __init__(self, words: List[str]):
        # self.words = set(words)
        self.Trie = Trie()
        self.maxlen = -1
        for w in words:
            self.maxlen = max(self.maxlen, len(w))
            rev = w[::-1]
            self.Trie.add(rev)
        self.searchArr = deque()
        

    def query(self, letter: str) -> bool:

        self.searchArr.insert(0, letter)
        if len(self.searchArr) > self.maxlen:
            self.searchArr.pop()

        tmpWord = \"\".join(self.searchArr)    
        return self.Trie.search(tmpWord)
#             return True        

#         return False    
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class node:
    def __init__(self):
        self.children = {}
        self.end = 0
        
class Trie:
    def __init__(self):
        self.root = node()
        
    def insert(self, w):
        r = self.root
        for l in w:
            r = r.children.setdefault(l, node())
        r.end = 1


class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.s = deque()
        for w in words: self.trie.insert(w[::-1])

    def query(self, letter: str) -> bool:
        self.s.appendleft(letter)
        cur = self.trie.root
        for c in self.s:
            if c in cur.children:
                cur = cur.children[c]
                if cur.end: return True 
            else: break
        return False


class TrieNode:
    def __init__(self):
        self.edges={}
    
    def get_edge(self,edge):
        return self.edges[edge]
    
    def add_edge(self,edge):
        if not self.has_edge(edge):
            self.edges[edge]=TrieNode()
            
    def has_edge(self,edge):
        return edge in self.edges
    
    def isWord(self):
        return \"$\" in self.edges
    
class Trie:
    
    def __init__(self):
        self.root=TrieNode()
        
    def insert(self,word):
        cur=self.root
        for c in word:
            cur.add_edge(c)
            cur=cur.get_edge(c)
        cur.add_edge(\"$\")
        
    def search(self, word):
        cur=self.root
        for c in word:
            if cur.isWord():
                return True
            if not cur.has_edge(c):
                return False
            cur=cur.get_edge(c)
        return cur.isWord()
from collections import deque
class StreamChecker:
    def __init__(self, W):
        self.prefix=deque()
        self.trie=Trie()
        for w in W:
            self.trie.insert(w[::-1])

    def query(self, c):
        self.prefix.appendleft(c)
        return self.trie.search(self.prefix)


\"\"\"
time:  9:00AM
Try defaultdict as well 

\"\"\"
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Node:
    def __init__(self, char):
        self.char = char
        self.nxts = {}
        self.end = False

class Trie:
    def __init__(self):
        self.root = Node('')
    
    def _add(self, node, word):
        if word == '':
            node.end = True
            return
        if word[0] not in node.nxts:
            node.nxts[word[0]] = Node(word[0])
        self._add(node.nxts[word[0]], word[1:])

    def add(self, word):
        self._add(self.root, word)
        
    def _search(self, node, word):
        if node.end is True:
            return True
        if word == '':
            return node.end is True
        if word[0] in node.nxts:
            return self._search(node.nxts[word[0]], word[1:])
        return False

    def search(self, word):
        return self._search(self.root, word)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        for w in words:
            self.trie.add(w[::-1])
        self.sofar = ''

    def query(self, letter: str) -> bool:
        self.sofar = letter + self.sofar
        # print(self.sofar)
        return self.trie.search(self.sofar)

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.fin = ''
        self.children = {}

    def add(self,s,i=0):
        if i==len(s):
            self.fin=s
            return
        if s[i] not in self.children:
            self.children[s[i]] = TrieNode()                    
        self.children[s[i]].add(s,i+1)

    def get(self,c):
        result = self.children.get(c,None)
        return result


class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = TrieNode()
        for w in words:
            self.root.add(w[::-1])
        self.hist=[]
        
    def query(self, letter: str) -> bool:
        self.hist.append(letter)
        node = self.root
        for l in reversed(self.hist):
            node = node.get(l)
            if node is None:
                return False
            if node.fin:
                return True
        return False
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        for word in words:
            self.trie.add(word[::-1])
        self.sb = []

    def query(self, letter: str) -> bool:
        self.sb.append(letter)
        i = len(self.sb)-1
        node = self.trie
        while i >= 0:
            if node.is_word:
                return True
            if self.sb[i] in node.words:
                node = node.words[self.sb[i]]
                i -= 1
            else:
                return False
        return node.is_word    
            

class Trie:
    def __init__(self):
        self.is_word = False
        self.prefix = ''
        self.words = {}
    
    def add(self, word):
        if not word:
            self.is_word = True
            return
        if word[0] in self.words:
            self.words[word[0]].add(word[1:])
        else:
            n = Trie()
            n.prefix = self.prefix + word[0]
            self.words[word[0]] = n
            self.words[word[0]].add(word[1:])



# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.prefix = {}
        self.maxlen = 0
        for word in words:
            for i in range(len(word)-1, -1, -1):
                if word[i:][::-1] not in self.prefix:
                    self.prefix[word[i:][::-1]] = 0
            self.prefix[word[::-1]] = 1
            self.maxlen = max(self.maxlen, len(word))
        self.stack = []
        

    def query(self, letter: str) -> bool:
        self.stack.append(letter)
        for i in range(len(self.stack)-1, -1, -1):
            if len(self.stack[i:]) > self.maxlen:
                break
            temp = ''.join(self.stack[i:][::-1])
            if temp not in self.prefix:
                return False
            if self.prefix[temp] == 1:
                return True
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
    def __init__(self, words):
        self.trie = dict()
        for word in words:
            t = self.trie
            for c in reversed(word):
                if c not in t:
                    t[c] = dict()
                t = t[c]
            t['#'] = True
        self.stack = []
    def query(self, letter):
        self.stack.append(letter)
        t = self.trie
        for c in reversed(self.stack):
            if '#' in t:
                return True
            if c not in t:
                return False
            t = t[c]
        return '#' in t     # last check

    

    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
class StreamChecker:
    def __init__(self, words):
        self.trie = dict()
        for word in words:
            t = self.trie
            for c in reversed(word):
                if c not in t:
                    t[c] = dict()
                t = t[c]
            t['#'] = True
        self.stack = []
    def query(self, letter):
        self.stack.append(letter)
        t = self.trie
        for c in reversed(self.stack):
            if '#' in t:
                return True
            elif c in t:
                t = t[c]
            else:
                return False
        return '#' in t

        
        


from collections import defaultdict
class StreamChecker:

    def __init__(self, words: List[str]):
        self.helper = defaultdict(list)
        for i in words:
            self.helper[i[-1]].append(i)
        self.characters = \"\"

    def query(self, letter: str) -> bool:
        self.characters += letter
        if letter in self.helper:
            for j in self.helper[letter]:
                if self.characters[-len(j):] == j: return True
        return False
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Trie:
    def __init__(self):
        self.childern = defaultdict(Trie)
        self.end = False
        
class StreamChecker:
    def __init__(self, words: List[str]):
        self.inTrie = Trie()
        self.querystr = \"\"
        for word in words:
            self.addWord(word[::-1])
                
    def addWord(self, word):
        node = self.inTrie
        for symbol in word:
            node = node.childern[symbol]
        node.end = True
    
    def search(self, node, word):
        if not word:
            return node.end == True
        if node.end:
            return True
        node = node.childern.get(word[0])
        if not node:
            return False
        return self.search(node, word[1:])
        
    def query(self, letter: str) -> bool:
        self.querystr = letter + self.querystr
        return self.search(self.inTrie, self.querystr)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self):
        self.children, self.end_node = {}, 0
         
class Trie:
    def __init__(self):
        self.root = TrieNode()

    def insert(self, word):
        root = self.root
        for symbol in word:
            root = root.children.setdefault(symbol, TrieNode())
        root.end_node = 1

class StreamChecker:
    def __init__(self, words):
        self.trie = Trie()
        self.Stream = deque()
        for word in words: self.trie.insert(word[::-1])
         
    def query(self, letter):
        self.Stream.appendleft(letter)
        cur = self.trie.root
        for c in self.Stream:
            if c in cur.children:
                cur = cur.children[c]
                if cur.end_node: return True
            else: break
        return False
    
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
    def __init__(self, words: List[str]):
        self.q = ''
        self.m = defaultdict(set)
        for w in words:
            self.m[w[-1]].add(w)
        

    def query(self, letter: str) -> bool:
        self.q += letter
        return any(filter(lambda w: self.q.endswith(w), self.m[letter]))

class Trie:
    def __init__(self):
        self.letters = {}
        self.hasWord = False
    
    def addWord(self, word: str) -> None:
        if word == \"\":
            self.hasWord = True
            return
        if word[-1] not in self.letters:
            self.letters[word[-1]] = Trie()
        self.letters[word[-1]].addWord(word[:-1])
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.history = []
        self.trie = Trie()
        for w in words:
            self.trie.addWord(w)
        
    def query(self, letter: str) -> bool:
        t = self.trie
        self.history.append(letter)
        for x in reversed(self.history):
            if t.hasWord:
                return True
            if x not in t.letters:
                return False
            t = t.letters[x]
        return t.hasWord


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Trie:
    def __init__(self):
        self.endOfWord=False
        self.children=[None]*26
    def insert(self,s):
        t=self
        for c in s:
            if t.children[ord(c)-ord('a')]==None:
                t.children[ord(c)-ord('a')]=Trie()
            t=t.children[ord(c)-ord('a')]
        t.endOfWord=True
    def search(self,s):
        t=self
        for c in s:
            if t.children[ord(c)-ord('a')]==None: 
                return False
            t=t.children[ord(c)-ord('a')]
            if(t.endOfWord): 
                return True
        return False
class StreamChecker:

    def __init__(self, words: List[str]):
        self.t=Trie()
        self.stream = collections.deque()
        for w in words:
            self.t.insert(reversed(w))
        

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        return self.t.search(self.stream)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.word_set = set(words)
        self.last_letter_set = set()
        self.max_len = 0
        self.min_len = math.inf
        for w in words:
            self.last_letter_set.add(w[-1])
            if len(w) > self.max_len:
                self.max_len = len(w)
            if len(w) < self.min_len:
                self.min_len = len(w)
        self.s = \"\"

    def query(self, letter: str) -> bool:
        self.s += letter
        if letter in self.last_letter_set:
            for i in range(max(len(self.s)-self.max_len, 0), len(self.s)-self.min_len+1):
                if self.s[i:] in self.word_set:
                    return True
        return False
        

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self):
        self.children = collections.defaultdict(lambda: TrieNode())
        self.word = False

class Trie:
    def __init__(self):
        self.root = TrieNode()
        
    def insert(self, word):
        node = self.root
        for c in word: node = node.children[c]
        node.word = True
        
    def search(self, word, prefix=False):
        node = self.root
        for c in word:
            if c not in node.children: return False
            node = node.children[c]
        if prefix: return True
        return node.word
    
    def starswith(self, prefix):
        return self.search(prefix, True)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        for w in words: self.trie.insert(w[::-1])
        self.stream = []
    def query(self, letter: str) -> bool:
        self.stream += [letter]
        #print(self.stream)
        for i in range(1, len(self.stream)+1):
            #print(i, self.stream[-i:])
            if not self.trie.search(self.stream[-i:][::-1], True): return False
            if self.trie.search(self.stream[-i:][::-1]): return True


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.letters = []
        # build trie
        for word in words:
            p = self.trie # makre sure point to root for each word
            for ch in word[::-1]:
                if ch not in p:
                    p[ch] = {}
                p = p[ch]
            p['#'] = {}

    def query(self, letter: str) -> bool:
        self.letters.append(letter)
        # lookup trie in reverse order
        p = self.trie
        for i in range(len(self.letters) - 1, -1, -1):
            ch = self.letters[i] 
            if ch not in p:
                return False
            p = p[ch]
            if '#' in p:
                return True
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

\"\"\"
[\"cd\",\"f\",\"kl\"]
        root
     d   f.   l
   c             k

      reverse check <-
a b c d e f g h i j k l
      ^

\"\"\"


class Trie():
    def __init__(self):
        self.isWord = False
        self.children = {}

class StreamChecker:

    def __init__(self, words: List[str]):
        self.StreamChecker = Trie()
        self.letters = []
        for word in words:
            self.addWord(word)
            
    def query(self, letter: str) -> bool:
        self.letters.insert(0,letter)
        node = self.StreamChecker
        for letter in self.letters:
            if node.isWord == True:
                return True
            if letter not in node.children:
                return False
            node = node.children[letter]

        if node.isWord == True:
            return True
        else:
            return False
            

    def addWord(self, word):
        node = self.StreamChecker
        word = word[::-1]
        for letter in word:
            if letter not in node.children:
                node.children[letter] = Trie()
            node = node.children[letter]
        node.isWord = True
        

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from typing import List, Dict, Optional, Iterator


class TrieNode:
    def __init__(self, value: Optional[str]) -> None:
        self.value = value
        self.children: Dict[str, TrieNode] = {}

        self.end = False
        self.word: Optional[str] = None  # not necessary in this task


def build_trie(words: List[str]) -> TrieNode:
    trie_root = TrieNode(None)

    for word in words:
        trie_node = trie_root

        for char in word:
            trie_node.children.setdefault(char, TrieNode(char))
            trie_node = trie_node.children[char]

        trie_node.end = True
        trie_node.word = word

    return trie_root


class StreamCheckerForward:
    def __init__(self, words: List[str]) -> None:
        self._trie = build_trie(words)
        self._trie_ptrs = [self._trie]

    def query(self, letter: str) -> bool:
        trie_ptrs_new = [self._trie]

        result = False

        for trie_node in self._trie_ptrs:
            if letter in trie_node.children:
                result = result or trie_node.children[letter].end
                trie_ptrs_new.append(trie_node.children[letter])

        self._trie_ptrs = trie_ptrs_new

        return result


class StreamChecker:
    def __init__(self, words: List[str]) -> None:
        self._trie = build_trie(list(map(reversed, words)))
        self._stream = []

    def _search_trie(self, stream: Iterator[str]) -> bool:
        node = self._trie

        for char in stream:
            if node.end:
                return True

            if char in node.children:
                node = node.children[char]
            else:
                break

        return node.end

    def query(self, letter: str) -> bool:
        self._stream.append(letter)

        return self._search_trie(reversed(self._stream))


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    def __init__(self):
        self.endOfWord = False
        self.children = [None]*26
    
    def insert(self, s):
        t = self
        for c in s:
            if t.children[ord(c)-ord('a')] == None:
                t.children[ord(c)-ord('a')] = Trie()
            t = t.children[ord(c)-ord('a')]
        t.endOfWord = True
        
    
    def search(self, s):
        t = self
        for c in s:
            if t.children[ord(c)-ord('a')] == None:
                return False
            t = t.children[ord(c)-ord('a')]
            if t.endOfWord :
                return True
        #when all the characters are there in the word but there is no end of the word
        return False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.t = Trie()
        self.stream = collections.deque()
        for w in words:
            self.t.insert(reversed(w))

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        return self.t.search(self.stream)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.rec = collections.defaultdict(set)
        self.maxsize = float('-inf')
        self.minsize = float('inf')
        for w in words:
            self.maxsize = max(len(w), self.maxsize)
            self.minsize = min(len(w), self.minsize)
            self.rec[w[-1]].add((w,len(w)))

        self.curr = \"\"

    def query(self, letter: str) -> bool:
        
        self.curr += letter        
        for w, i in self.rec[letter]:
            if i <= len(self.curr) and self.curr[-i:] == w:
                return True            
            
        self.curr = self.curr[-self.maxsize:]
            
        return False
            
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:
    #reverse the streamer and put it in trie
    def __init__(self, words: List[str]):
        
        self.now = ''
        self.trie = defaultdict()
        

        for w in words:
            cur = self.trie
            for i in w[::-1]:
                if i not in cur:
                    cur[i] = defaultdict()
                
                cur = cur[i]
            cur['#'] = None
                

    def query(self, letter: str) -> bool:
        self.now+=letter
        
        
        s = self.now[::-1]
        cur = self.trie
        for i in s:
            if i in cur:
                cur=cur[i]
                if '#' in cur:
                    return True
            else:
                break
        return False
            
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.tries = {}
        self.hist = ''
        for word in words:
            cur = self.tries            
            for c in word[::-1]:
                if c not in cur:
                    cur[c] = {}
                cur = cur[c]
            cur['#'] = word

    def query(self, letter: str) -> bool:
        self.hist += letter
        cur = self.tries
        for c in self.hist[::-1]:
            if '#' in cur:
                return True
            if c in cur:
                cur = cur[c]
            else:
                return False
        return '#' in cur

    
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.tries = {}
        self.hist = ''
        for word in words:
            cur = self.tries            
            for c in word[::-1]:
                if c not in cur:
                    cur[c] = {}
                cur = cur[c]
            cur['#'] = word
        print((self.tries))

    def query(self, letter: str) -> bool:
        self.hist += letter
        cur = self.tries
        for c in self.hist[::-1]:
            if '#' in cur:
                return True
            if c in cur:
                cur = cur[c]
            else:
                return False
        return '#' in cur

    
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    def __init__(self):
        self.root = Node()
    
    def add(self, word):
        curr = self.root
        for c in word:
            if curr.has(c):
                curr = curr.child(c)
            else:
                curr.add(c)
                curr = curr.child(c)
        curr.end()
        
    def search(self, word):
        curr = self.root
        for c in word:
            if curr.terminal:
                return True
            elif not curr.has(c):
                return False
            else:
                curr = curr.child(c)
        return curr.terminal
        
    def display(self):
        def recurse(node, pref):
            print (''.join(pref), node.terminal)
            for letter, child in node.children.items():
                recurse(child, pref + [letter])
        
        pref = []
        recurse(self.root, pref)
        
class Node:
    def __init__(self):
        self.children = {}
        self.terminal = False
        
    def end(self):
        self.terminal = True
    
    def has(self, c):
        return c in self.children
    
    def add(self, c):
        self.children[c] = Node()
    
    def child(self, c):
        return self.children[c]
    
    def __str__(self):
        return \"nd\"
    
    def __repr__(self):
        return \"nd\"
    

def rev(L):
    # reverse iterator
    for i in range(len(L) - 1, -1, -1):
        yield L[i]
    
class StreamChecker:
    def __init__(self, words: List[str]):
        # Set trie up for reverses of words
        # always search in reverse
        self.T = Trie()
        for word in words:
            self.T.add(rev(word))
        self.stream = []
        self.T.display()
        
        
    def query(self, letter: str) -> bool:
        self.stream.append(letter)
        return self.T.search(rev(self.stream))

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:
    word=[]
    d={}
    queryseq=\"\"
    def __init__(self, words: List[str]):
        self.word=[]
        self.d={}
        self.queryseq=\"\"
        for i in range(len(words)):
            self.word.append(words[i])
            ch=words[i][-1]
            if ch in self.d:
                self.d[ch].append(i)
            else:
                self.d[ch]=[i]
        #print (self.d)

    def query(self, letter: str) -> bool:
        self.queryseq+=letter
        ch=letter[-1]
        if ch not in self.d:
            return False
        for i in self.d[ch]:
            x=self.word[i]
            if self.queryseq[-len(x):] ==x:
                return True
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            node = self.trie
            for c in word[::-1]:
                node = node.setdefault(c, {})
            node[\"$\"] = True
        self.stream = collections.deque([])
        
    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        node = self.trie
        for c in self.stream:
            if '$' in node:
                return True
            if c not in node:
                return False
            node = node[c]
        return \"$\" in node


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class trie:
    def __init__(self):
        self.endofword = False
        self.children = [None]*26
        
    def insert(self,s):
        t = self
        for i in s:
            if t.children[ord(i)-ord('a')] == None:
                t.children[ord(i)-ord('a')] = trie()
            t = t.children[ord(i)-ord('a')]
        t.endofword = True
        
    def search(self,w):
        t = self
        for i in w:
            if t.children[ord(i)-ord('a')] == None:
                return False
            t = t.children[ord(i)-ord('a')]
            if t.endofword:
                return True
        return False   
    
class StreamChecker:

    def __init__(self, words: List[str]):
        self.t = trie()
        self.dequeue = []
        for i in words:
            self.t.insert(reversed(i))
            

    def query(self, letter: str) -> bool:
        self.dequeue.insert(0,letter)
        return self.t.search(self.dequeue)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = dict()
        self.query_buffered = \"\"
        for word in words:
            tmp = self.trie
            for w in word[::-1]:
                if w not in tmp:
                    tmp[w] = dict()
                    tmp = tmp[w]
                else:
                    tmp = tmp[w]
            tmp['#HasWord#'] = True
        
        

    def query(self, letter: str) -> bool:
        tmp = self.trie
        self.query_buffered += letter
        for c in self.query_buffered[::-1]:
            if \"#HasWord#\" in tmp:
                return True
            if c in tmp:
                tmp = tmp[c]
            else:
                return False
        return \"#HasWord#\" in tmp        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

#class StreamChecker:

    #def _sum_ord(self, word: str):
     #   return sum([ord(c) for c in word])
    
    #def __init__(self, words: List[str]):
        
     #   self.ord_list = [ self._sum_ord(word) for word in words ]
      #  self.curr_ord = 0
       # self.
        #print(self.ord_list)
        
    #def query(self, letter: str) -> bool:
     #   self.curr_ord += ord(letter)
        
      #  if self.curr_ord in self.ord_list:
       #     self.curr_ord = 0
        #    return True
       # else:
        #    return False


class StreamChecker(object):

    def __init__(self, words):
        self.word_map, self.len_map, self.buffer = defaultdict(set), defaultdict(set), \"\"
        for w in words:
            self.word_map[w[-1]].add(w[::-1])
            self.len_map[w[-1]].add(len(w))
        

    def query(self, letter):
        self.buffer = letter + self.buffer
        return any(len(self.buffer) >= l and self.buffer[:l] in self.word_map[letter] for l in self.len_map[letter])
        
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Trie:
    def __init__(self):
        self.endOfWord = False
        self.children = [None] * 26
        
    def insert(self, s):
        t = self
        for c in s:
            if t.children[ord(c) - ord('a')] == None:
                t.children[ord(c) - ord('a')] = Trie()
            t = t.children[ord(c) - ord('a')]
        t.endOfWord = True
        
    def search(self, s):
        t = self
        for c in s:
            if t.children[ord(c) - ord('a')] == None:
                return False
            t = t.children[ord(c) - ord('a')]
            if t.endOfWord:
                return True
        return False
    
    


class StreamChecker:

    def __init__(self, words: List[str]):
        self.t = Trie()
        self.stream = collections.deque()
        for w in words:
            self.t.insert(reversed(w))
            
        
    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        return self.t.search(self.stream)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    class Node:
        def __init__(self):
            self.node = [None] * 26
            self.end = False
    def __init__(self, words: List[str]):
        self.s = ''
        self.root = self.Node()
        for word in words:
            node = self.root
            n = len(word)
            word = word[::-1]
            for i in range(n):
                a = ord(word[i]) - ord('a')
                if not node.node[a]:
                    node.node[a] = self.Node()
                if i == n - 1:
                    node.node[a].end = True
                else:
                    node = node.node[a]
            print((node.node, node.end))

    def query(self, letter: str) -> bool:
        self.s = letter + self.s
        node = self.root
        for i in self.s:
            a = ord(i) - ord('a')
            if not node.node[a]:
                return False
            if node.node[a].end:
                print((not node.node[a]))
                return True
            node = node.node[a]
        return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words):
        self.s = ''
        self.dic = collections.defaultdict(set)
        for w in words:
            self.dic[w[-1]].add(w)

    def query(self, letter: str) -> bool:
        self.s += letter
        return any(self.s.endswith(w) for w in self.dic[letter])


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.s = ''
        self.dic = collections.defaultdict(set)
        for w in words:
            self.dic[w[-1]].add(w)

    def query(self, letter: str) -> bool:
        self.s += letter
        return any(self.s.endswith(w) for w in self.dic[letter])
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.map = {}
        self.history = ''
        
        for w in words:
            curr = self.map
            w = w[::-1]
            w += '0'
            for c in w:
                if c not in curr:
                    curr[c] = {}
                curr = curr[c]
            # curr['is_end'] = True

    def query(self, letter: str) -> bool:
        self.history += letter
        curr = self.map
        
        for c in self.history[::-1]:
            if c not in curr:
                break
            curr = curr[c]
            if '0' in curr:
                return True
        
        return False
        

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import defaultdict
def tree():
    return defaultdict(tree)

class StreamChecker:
    def __init__(self, words: List[str]):
        # we store the words in an inverse trie (nexted dictionary) because when we get a new query we would know the last character to match and from that if we move upwards we will know whether we reach the top or not if we do we found our word else we return False  
        # to achieve this we need to construct an inverse trie and thus we won't have multiple choices to match we would only have a single choice for each character
        self.trie = defaultdict(tree)
        for word in words:
            node = self.trie
            for char in word[::-1]:
                node = node[char]
            node['*'] = 1
        self.current_list = []
        
#         self.print_nested(self.trie)
        
#     def print_nested(self, d, indent=0):
#         for k, v in d.items():
#             print ('{}{!r}:'.format(indent * '  ', k))
#             if type(v) is not int:
#                 self.print_nested(v, indent + 1)

    def query(self, letter: str) -> bool:
        # there are two reasons for returning false one is that we did not find a matching character in the tire for the current letter in which case we can empty the entire list
        # else if we found a matching a character but its not marking the end of the search(here beginning of the word) we add it to the list and return False
        # currently we will store the words in a simple list if we return false for them and if we return true we remove them from the list
        # we first travel down the trie
        match_found = True
        end_found = False
        self.current_list.insert(0,letter)
        i = 0
        node = self.trie
        while i < len(self.current_list):
            if self.current_list[i] in list(node.keys()):
                node = node[self.current_list[i]]
                if '*' in list(node.keys()):
                    end_found = True
                    break
            else:
                match_found = False
                break
            i += 1      
        if '*' in list(node.keys()):
            end_found = True
        # if (not match_found):
        #     self.current_list = [letter]
        return end_found
    
    # for the following approach only `6 out of 17 test cases pass and so when we are travelling the stack the time limit exceeds this is because with the stack approach we are searching the words from the begining to the end and we do not know how many characters to match 
    '''
    def __init__(self, words: List[str]):
        # we store the words in a trie (nested defaultdictionary)
        self.trie = defaultdict(tree)
        for word in words:
            node = self.trie
            for char in word:
                node = node[char]
            node['*'] = 1
        self.pointers_stack = []
        # we keep a list of pointers which mark the beginnign of the words in the trie based on the queries in the trie and if we return True we just increment the last pointer in the pointers heirarchy to point to the new root down the hierarchy and if there is a new word that starts 
        # if we return False because we cannot find the current character in the current pointer we change the pointer to point to the beginning and if there is a word starting from that character we change it to it else we keep it null
        # if we return False because we have not yet reached the end of the word however we have a corresponding character in the current pointer then we make a new entry to the pointers list which marks that this character may be because a new word has begun change the pointer to point to the latest character 
        
    # def print_nested(self, d, indent=0):
    #     for k, v in d.items():
    #         print ('{}{!r}:'.format(indent * '  ', k))
    #         self.print_nested(v, indent + 1)

    def query(self, letter: str) -> bool:
        # we keep on poping elements from the pointer stack as they mark the beginning of the words 
        # so our stack will be like [#q1q2q3, #q2q3, #q3] (actually it will be [#q3,#q3,#q3] and all q3 will be different nodes ) if we find the current character in q3 we increment the pointer in the last element and so now our stack becomes [#q1q2q3, #q2q3, #q3q4] -
        # we keep on travelling the stack and if we do not find q4 somewhere we pop that node else we add q4 by incrementing the pointer till for all the elements in the stack
        # eg there is no word starting with q2 and having q4 while there are some words having #q1q2q3q4 and #q3q4 format then our stack will look like [#q1q2q3q4, #q3q4] 
        # if for some value we find a word ending in q4 we return True else we return False
        answer = False
        if self.pointers_stack != []:
            index = 0
            while index < len(self.pointers_stack) and self.pointers_stack != []:
                root = self.pointers_stack[index]
                if letter in root.keys():
                    self.pointers_stack[index] = root[letter]
                    if root[letter]['*'] == 1:
                        answer = True
                    index += 1
                else:
                    self.pointers_stack.pop(index)
        # finally we also need to add the current letter as a start of the word
        if letter in self.trie.keys():
            root = self.trie[letter]
            self.pointers_stack.append(root)
            if root['*'] == 1:
                answer = True
        return answer
        
    '''
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
    END = \"#\"

    def __init__(self, words: List[str]):
        self.trie = self.build_trie(words)
        self.prefix = collections.deque()
        
    def build_trie(self, words: list):
        trie = {}
        for word in words:
            root = trie
            for char in reversed(word):
                root = root.setdefault(char, {})
            root[self.END] = word
        return trie

    def query(self, letter: str) -> bool:
        self.prefix.appendleft(letter)
        root = self.trie
        
        for char in self.prefix:
            if char in root:
                root = root[char]
                if self.END in root:
                    return True
            else:
                break
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self):
        self.children = [None]*26
        self.end = False

class StreamChecker:

    def char_to_index(self, ch):
        return ord(ch) - ord('a')

    def insert(self, word):
        n = len(word)
        ptr = self.root
        for lvl in range(len(word)-1,-1,-1):
            i = self.char_to_index(word[lvl])
            if ptr and not ptr.children[i]:
                ptr.children[i] = TrieNode()

            ptr = ptr.children[i]

        ptr.end = True

    def __init__(self, words):
        self.root = TrieNode()
        self.pe = \"\"

        for word in words:
            self.insert(word)

    def query(self, letter):
        self.pe = letter + self.pe
        n = len(self.pe)
        node = self.root
        for lvl in range(n):
            i = self.char_to_index(self.pe[lvl])
            if node.children[i]:
                if node.children[i].end:
                    return True
            else:
                return False
            
            node = node.children[i]
            if not node:
                return False
       


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:


    def __init__(self, words: List[str]):
        self.root = {}
        self.end = -1
        for w in words:
            self.insert(w)
        self.qhist = ''

    def insert(self, word):
        curNode = self.root
        for c in word[::-1]:
            if not c in curNode:
                curNode[c] = {}
            curNode = curNode[c]
        curNode[self.end] = True

    def query(self, letter: str) -> bool:
        self.qhist += letter
        curNode = self.root
        for c in self.qhist[::-1]:
            if not c in curNode:
                return False
            curNode = curNode[c]
            if self.end in curNode:
                return True




# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.s = ''
        self.dic = collections.defaultdict(set)
        for w in words:
            self.dic[w[-1]].add(w)

    def query(self, letter: str) -> bool:
        self.s += letter
        return any(self.s.endswith(w) for w in self.dic[letter])
        
# class TrieNode:
#     def __init__(self, letter, next=None, isWord=False):
#         self.letter = letter
#         self.next = next
#         self.isWord = isWord
    
#     def setNext(next):
#         self.next = next
    
#     def isWord():
#         return self.isWord
    
#     def setWord(flag):
#         self.isWord = flag
        
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)



class StreamChecker:

    def __init__(self, words):
        self.history = \"\"
        self.map = {}
        
        for word in words:  
            curr_node = self.map
            for letter in word[::-1]:   
                if letter not in curr_node:
                    curr_node[letter] = {}  
                curr_node = curr_node[letter]   
            curr_node['end'] = True

    def query(self, letter: str) -> bool:
        self.history += letter

        curr_node = self.map
        for l in self.history[::-1]:

            if l not in curr_node:
                return False
                    
            curr_node = curr_node[l]
        
            if 'end' in curr_node:
                return True
        
        return False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.history = \"\"
        self.map = {}
        
        for word in words:
            curr_node = self.map
            for letter in word[::-1]:
                if letter not in curr_node:
                    curr_node[letter] = {}
                curr_node = curr_node[letter]
            curr_node['#'] = {}

    def query(self, letter: str) -> bool:
        self.history += letter

        curr_node = self.map
        for l in self.history[::-1]:

            if l not in curr_node:
                return False
                    
            curr_node = curr_node[l]
        
            if '#' in curr_node:
                return True
        
        return False

class Trie:
    def __init__(self):
        self.root = {\"0\": \"0\"}
    
    def add_w(self, w):
        cn = self.root
        for i in w[::-1]:
            if i not in cn:
                cn[i] = {}
            cn = cn[i]
        cn[\"*\"] = \"*\"
    
    def search(self, w):
        cn = self.root
        for i in w[::-1]:
            if \"*\" in cn:
                return True
            if i not in cn:
                return False
            cn = cn[i]
        return \"*\" in cn


class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie = Trie()
        for i in words:
            self.trie.add_w(i)
        self.string = \"\"
        
    def query(self, letter: str) -> bool:
        self.string += letter
        return self.trie.search(self.string)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:
    def __init__(self, words: List[str]):
        self.history = ''
        self.map = {}
        for word in words:
            curr_node = self.map
            for letter in word[::-1]:
                if letter not in curr_node:
                    curr_node[letter] = {}
                curr_node = curr_node[letter]
            curr_node['#'] = {}

    def query(self, letter: str) -> bool:
        self.history += letter
        curr_node = self.map
        for l in self.history[::-1]:
            if l not in curr_node:
                return False
            curr_node = curr_node[l]
            if '#' in curr_node:
                return True
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    def __init__(self):
        self.trie = {}
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.word = \"\"
        self.reversed_list = []
        for i in words:
            self.add_word(i[::-1])
    def add_word(self,word):
        curr = self.trie 
        for ch in word:
            if ch not in curr:
                curr[ch] = {}
            curr = curr[ch]
        curr[\"*\"] = True


    def query(self, letter: str) -> bool:
        self.word +=letter
        curr = self.trie
        
        for i in self.word[::-1]:
            if \"*\" in curr:
                return True
            if i not in curr:
                return False
            curr = curr[i]
        return \"*\" in curr
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self):
        self.children = {}
        self.isEnd = False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.q = ''
        self.root = TrieNode()
        for word in words:
            root = self.root
            for w in word[::-1]:
                root = root.children.setdefault(w, TrieNode())
            root.isEnd = True
            
    def dfs(self, node, n) -> bool: 
        # n: pos back from self.q
        if n > len(self.q): return False
        if self.q[-n] in node.children:
            if node.children[self.q[-n]].isEnd:
                return True
            else:
                return self.dfs(node.children[self.q[-n]], n + 1)
        else:
            return False     
                
    def query(self, letter: str) -> bool:
        self.q += letter
        return self.dfs(self.root, 1)
        
        
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.stream = []
        
        for word in words:
            node = self.trie
            for ch in word[::-1]:
                if ch not in node:
                    node[ch] = {}
                node = node[ch]
            node['#'] = {}
                    

    def query(self, letter: str) -> bool:
        self.stream.append(letter)
        
        node = self.trie
        for i in range(len(self.stream)-1,-1,-1):
            if self.stream[i] not in node:
                return False
            else:
                node = node[self.stream[i]]
                if '#' in node:                
                    return True
            
        
        return False 
    
            
            
            
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.words = words
        self.trie = {}
        self.history = ''
        for w in words:
            p = self.trie
            for c in w[::-1]:
                if c not in p: p[c] = {}
                p = p[c]
            p['#'] = ''

    def query(self, letter: str) -> bool:
        self.history+=letter
        p = self.trie
        for c in self.history[::-1]:
            if c not in p: break
            p = p[c]
            if '#' in p: return True
        return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self, ch):
        self.ch = None
        self.children = {}
        self.isWord = False

class Trie:
    def __init__(self, words):
        self.root = TrieNode(None)
        for word in words:
            self.insert(word[::-1])
            
        return
    
    def insert(self, word):
        cur = self.root
        for ch in word:
            if ch not in cur.children:
                newNode = TrieNode(ch)
                cur.children[ch] = newNode
            
            cur = cur.children[ch]
            
        cur.isWord = True
        
    def search(self, word):
        cur = self.root
        for ch in word[::-1]:
            if cur.isWord:
                return True
            if ch not in cur.children:
                return False
            cur = cur.children[ch]
            
        return cur.isWord
            


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trieTree = Trie(words)
        self.curr = ''

    def query(self, letter: str) -> bool:
        self.curr += letter
        return self.trieTree.search(self.curr)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.history = \"\"
        self.map = {}
        
        for word in words:
            curr_node = self.map
            for letter in word[::-1]:
                if letter not in curr_node:
                    curr_node[letter] = {}
                curr_node = curr_node[letter]
            curr_node['#'] = {}

    def query(self, letter: str) -> bool:
        self.history += letter

        curr_node = self.map
        for l in self.history[::-1]:

            if l not in curr_node:
                return False
                    
            curr_node = curr_node[l]
        
            if '#' in curr_node:
                return True
        
        return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.history = \"\"
        self.map = {}
        
        for word in words:
            curr_node = self.map
            for letter in word[::-1]:
                if letter not in curr_node:
                    curr_node[letter] = {}
                curr_node = curr_node[letter]
            curr_node['/'] = {}

    def query(self, letter: str) -> bool:
        self.history += letter

        curr_node = self.map
        for l in self.history[::-1]:

            if l not in curr_node:
                return False
                    
            curr_node = curr_node[l]
        
            if '/' in curr_node:
                return True
        
        return False
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Trie():
    def __init__(self):
        self.dic = {}
        
    def insert(self, words):
        cur = self.dic
        for word in words:
            if word not in cur:
                cur[word] = {}
            cur = cur[word]
        cur['#'] = True
    
    def search(self, words):
        cur = self.dic
        for word in words:
            if '#' in cur:
                return True
            if word not in cur:
                return False
            cur = cur[word]
        return '#' in cur

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        #self.q = deque()
        self.s = \"\"
        for word in words:
            self.trie.insert(word[::-1])    

    def query(self, letter: str) -> bool:
        #self.q.appendleft(letter)
        self.s += letter
        return self.trie.search(self.s[::-1])
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self):
        self.nodes = defaultdict(TrieNode)
        self.isWord = False
        
class StreamChecker:
    def __init__(self, words: List[str]):
        self.trieRoot = TrieNode()
        self.stream = \"\"
        self.words = {}
        self.minWordLen = float(\"inf\")
        
        for word in words:
            self.addWord(word[::-1])
            if len(word) < self.minWordLen:
                self.minWordLen = len(word)
        
    def addWord(self, word: str) -> None:
        \"\"\"
        Adds a word into the data structure.
        \"\"\"
        current_node = self.trieRoot
        #print(\"Inserting =\", word)
        for char in word:
            #print(\"Char =\", char)
            current_node = current_node.nodes[char]
        
        current_node.isWord = True
        self.words[word] = True
        #print(self.words)
    
    def query(self, letter: str) -> bool:
        self.stream += letter
        word = self.stream[::-1]
        
        curr = self.trieRoot
        
        for char in word:
            #print(\"One by one:\", char)
            if char not in curr.nodes:
                #print(\"returning False\")
                return False
            curr = curr.nodes[char]
            if curr.isWord:
                return True

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.history = \"\"
        self.map = {}
        
        for word in words:
            curr_node = self.map
            for letter in word[::-1]:
                if letter not in curr_node:
                    curr_node[letter] = {}
                curr_node = curr_node[letter]
            curr_node['#'] = {}

    def query(self, letter: str) -> bool:
        self.history += letter

        curr_node = self.map
        for l in self.history[::-1]:

            if l not in curr_node:
                return False
                    
            curr_node = curr_node[l]
        
            if '#' in curr_node:
                return True
        
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

# class StreamChecker:

#     def __init__(self, words: List[str]):
#         # self.words=words
#         self.last=defaultdict(list)
#         for _ in words:
#             self.last[_[-1]].append(_)
#         self.read=[]

#     def query(self, letter: str) -> bool:
#         self.read.append(letter)
#         ret=False
#         poss=self.last.get(letter)
#         if poss:
#             for _ in poss:
#                 ind=len(self.read)-1
#                 suc=True
#                 for i in range(len(_)-1,-1,-1):
#                     if ind == -1:break
#                     if self.read[ind]!=_[i]:
#                         suc=False
#                         break
#                     ind-=1
#                 if suc:
#                     ret=suc
#                     break
#         return ret
                

# # Your StreamChecker object will be instantiated and called as such:
# # obj = StreamChecker(words)
# # param_1 = obj.query(letter)
class StreamChecker:

    def __init__(self, words: List[str]):
        self.history = \"\"
        self.map = {}
        
        for word in words:
            curr_node = self.map
            for letter in word[::-1]:
                if letter not in curr_node:
                    curr_node[letter] = {}
                curr_node = curr_node[letter]
            curr_node['#'] = {}

    def query(self, letter: str) -> bool:
        self.history += letter

        curr_node = self.map
        for l in self.history[::-1]:

            if l not in curr_node:
                return False
                    
            curr_node = curr_node[l]
        
            if '#' in curr_node:
                return True
        
        return False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.stream = deque([])

        for word in set(words):
            node = self.trie       
            for ch in word[::-1]:
                if not ch in node:
                    node[ch] = {}
                node = node[ch]
            node['$'] = word
        
        
    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        
        node = self.trie
        for ch in self.stream:
            if '$' in node:
                return True
            if not ch in node:
                return False
            node = node[ch]
        return '$' in node
            
        
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    
    def __init__(self):
        self.endOfWord = False
        self.children = [None]*26

    def insert(self, s):
        t = self
        for c in s:
            if t.children[ord(c)-ord('a')] == None:
                t.children[ord(c)-ord('a')] = Trie()
            t = t.children[ord(c)-ord('a')]
        t.endOfWord = True

    def search(self, s):
        t = self
        for c in s:
            if t.children[ord(c)-ord('a')] == None: return False
            t = t.children[ord(c)-ord('a')]
            if t.endOfWord: return True
        return False


class StreamChecker:

    def __init__(self, words: List[str]):
        self.t = Trie()
        self.stream = collections.deque()
        for w in words:
            self.t.insert(reversed(w))

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        return self.t.search(self.stream)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
  def __init__(self):
    self.children = collections.defaultdict(TrieNode)
    self.is_word = False

class Trie:
  def __init__(self):
    self.root = TrieNode()
    
  def add_words(self, words):
    for word in words:
      cur = self.root
      for l in word:
        cur = cur.children[l]
      cur.is_word = True

class StreamChecker:
  def __init__(self, words: List[str]):
    self.trie = Trie()
    self.trie.add_words([word[::-1] for word in words])
    self.prefix = ''

  def query(self, letter: str) -> bool:
    self.prefix += letter
    cur = self.trie.root

    for l in self.prefix[::-1]:
      if l not in cur.children:
        break

      cur = cur.children[l]
      if cur.is_word:
        return True

    return False
        
      
          
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        # self.stream = deque([])
        self.stream = []

        for word in set(words):
            node = self.trie       
            for ch in word[::-1]:
                if not ch in node:
                    node[ch] = {}
                node = node[ch]
            node['$'] = word
        
        
    def query(self, letter: str) -> bool:
        # self.stream.appendleft(letter)
        self.stream.insert(0,letter)
        
        node = self.trie
        for ch in self.stream:
            if '$' in node:
                return True
            if not ch in node:
                return False
            node = node[ch]
        return '$' in node
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import defaultdict
class StreamChecker:

    def __init__(self, words):
        self.s = ''
        self.dic = collections.defaultdict(set)
        for w in words:
            self.dic[w[-1]].add(w)
        print((self.dic))

    def query(self, letter: str) -> bool:
        self.s += letter
        return any(self.s.endswith(w) for w in self.dic[letter])

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    
    def __init__(self):
        self.dict = collections.defaultdict(TrieNode)
        self.isWord = False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.stream = ''
        
        self.root = TrieNode()
        for word in words:
            curr = self.root
            
            for char in word[::-1]:
                curr = curr.dict[char]
                
            curr.isWord = True
        

    def query(self, letter: str) -> bool:
        self.stream += letter
        curr = self.root
        for char in self.stream[::-1]:
            if char not in curr.dict:
                return False
            
            curr = curr.dict[char]
            if curr.isWord:
                return True
            

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        head = self.trie
        self.history = \"\"
        
        for w in words:
            p = head
            for i in range(len(w)-1, -1, -1):
                if i==0:
                    if w[i] not in p:
                        p[w[i]] = {'#' : True}
                    else:
                        p[w[i]]['#'] = True
                else:
                    if w[i] not in p:
                        p[w[i]] = {'#' : False}
                        p = p[w[i]]
                    else:
                        p = p[w[i]]
        print(self.trie)
                    

    def query(self, letter: str) -> bool:
        self.history += letter
        # print(self.history)
        head = self.trie
        for i in self.history[::-1]:
            # print(i)
            if i in head:
                if head[i]['#']==True:
                    return True
                else:
                    head =  head[i]
            else:
                return False
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:
    def __init__(self, words: List[str]):
        self.tree = Tree()
        for item in words:
            curr = self.tree
            for letter in item[::-1]:
                if letter not in curr.subtrees:
                    curr.subtrees[letter] = Tree()
                curr = curr.subtrees[letter]
            curr.food = True
        self.q = ''

    def query(self, letter: str) -> bool:
        self.q += letter
        reverse_q = self.q[::-1]
        curr = self.tree
        for letter in reverse_q:
            if letter not in curr.subtrees:
                return False
            else:
                curr = curr.subtrees[letter]
                if curr.food:
                    return True
        return False


class Tree:
    def __init__(self):
        self.food = False
        self.subtrees = {}

from collections import defaultdict

class TrieNode:
    def __init__(self):
        self.dict = defaultdict(TrieNode)
        self.is_word = False

class StreamChecker:
    def __init__(self, words: List[str]):
        # Build a trie with the words in reverse order\t\t
        
        # for user query record, init as empty string
        self.prefix = ''
        
        # for root node of trie, init as empty Trie
        self.trie = TrieNode()
        
        for word in words:
            curr_node = self.trie
            
\t\t\t# make word in reverse order
            word = word[::-1]
            
            for char in word:                
                curr_node = curr_node.dict[ char ]
            
\t\t\t# mark this trie path as a valid word
            curr_node.is_word = True

    def query(self, letter: str) -> bool:
        self.prefix += letter
        
        curr_node = self.trie
        for char in self.prefix[::-1]:
            if char not in curr_node.dict:
                # word not in trie
                break
            curr_node = curr_node.dict[char] # get into next node
            if curr_node.is_word:
                # found word
                return True
        # No match
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    
    def __init__(self):
        self.children = collections.defaultdict(TrieNode)
        self.is_word = False
        
        
class Trie:
    
    def __init__(self):
        self.root = TrieNode()
    
    def build(self, words):
        for word in words:
            self._insert(word[::-1])
            
    def _insert(self, word):
        cur = self.root
        for char in word:
            cur = cur.children[char]
        cur.is_word = True       
        
    def search(self, stream):
        cur = self.root
        for char in stream[::-1]:
            if char in cur.children:
                cur = cur.children[char]
                if cur.is_word:
                    return True
            else:
                return False
        return False
        

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.trie.build(words)
        self.stream = ''        

    def query(self, letter: str) -> bool:
        self.stream += letter
        found = self.trie.search(self.stream)
        return found
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            trie = self.trie
            for letter in word[::-1]:
                if letter in trie:
                    trie = trie[letter]
                else:
                    trie[letter] = {}
                    trie = trie[letter]
            trie['$'] = ''
        print((self.trie))
        self.queue = deque()    
        self.max_len = max(len(word) for word in words)

    def query(self, letter: str) -> bool:
        self.queue.appendleft(letter)
        if len(self.queue) > self.max_len:
            self.queue.pop()
        trie = self.trie
        for letter in self.queue:
            trie = trie.get(letter)
            if trie is None:
                return False
            if '$' in trie:
                return True
        return False
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.children = {}
        self.found = False
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = TrieNode()
        self.term = \"\"
        for w in words:
            cur = self.root
            for c in w[::-1]:
                if c not in cur.children:
                    cur.children[c] = TrieNode()
                cur = cur.children[c]
            cur.found = True

    def query(self, letter: str) -> bool:
        self.term += letter
        cur = self.root
        for c in self.term[::-1]:
            if cur.found:
                return True
            if c not in cur.children:
                break
            cur = cur.children[c]
        # self.term exists in the word list
        if cur.found:
            return True
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self):
        self.nodes = defaultdict(TrieNode)
        self.isWord = False
        
class StreamChecker:
    def __init__(self, words: List[str]):
        self.trieRoot = TrieNode()
        self.stream = \"\"
        
        for word in words:
            self.addWord(word[::-1])
    
    def addWord(self, word: str) -> None:
        \"\"\"
        Adds a word into the data structure.
        \"\"\"
        current_node = self.trieRoot
        for char in word:
            current_node = current_node.nodes[char]
        
        current_node.isWord = True
    
    def query(self, letter: str) -> bool:
        self.stream += letter
        word = self.stream[::-1]
        curr = self.trieRoot
        
        for char in word:
            if char not in curr.nodes:
                return False
            
            curr = curr.nodes[char]
            if curr.isWord:
                return True
            
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.letter = ''
        self.dic = collections.defaultdict(set)
        for w in words:
            self.dic[w[-1]].add(w)
        print(self.dic)
        

    def query(self, letter: str) -> bool:
        self.letter += letter
        for word in self.dic[letter]:
            if  self.letter.endswith(word):
                return True
            
        return False
            
            
                

    \"\"\"def query(self, letter: str) -> bool:
        self.s += letter
        return any(self.s.endswith(w) for w in self.dic[letter])
\"\"\"

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        
        # push the words in the trie in the reverse order 
        # now maintain a history of letters 
        # if the letters in the reverse of history are found in the trie then return true else return false
        
        self.trie = {}
        head = self.trie
        self.history = \"\"
        
        for w in words:
            p = head
            for i in range(len(w)-1, -1, -1):
                if i==0:
                    if w[i] not in p:
                        p[w[i]] = {'#' : True}
                    else:
                        p[w[i]]['#'] = True
                else:
                    if w[i] not in p:
                        p[w[i]] = {'#' : False}
                        p = p[w[i]]
                    else:
                        p = p[w[i]]
        print(self.trie)
                    

    def query(self, letter: str) -> bool:
        self.history += letter
        # print(self.history)
        head = self.trie
        for i in self.history[::-1]:
            # print(i)
            if i in head:
                if head[i]['#']==True:
                    return True
                else:
                    head =  head[i]
            else:
                return False
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = Trie()
        r = self.root
        self.maxLen = 0
        self.q = []
        for w in words:
            w = w[::-1]
            self.maxLen = max(len(w), self.maxLen)
            temp = r
            for c in w:
                if c in temp.c:
                    temp = temp.c[c]
                else:
                    temp.c[c] = Trie()
                    temp = temp.c[c]
            temp.end = True

    def query(self, l: str) -> bool:
        q = self.q
        n = self.maxLen
        r = self.root
        q.append(l)
        if len(q)>n:
            q.pop(0)
        def dfs(s,node):
            if len(s)==0:
                return node.end
            if node.end:
                return True
            if s[0] in node.c:
                return dfs(s[1:],node.c[s[0]])
            else:
                return False
        ans = dfs(q[::-1],r)
        return ans
            

class Trie:
    def __init__(self):
        self.end = False
        self.c = {}
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    
    def __init__(self):
        
        self.nodes = {}
        self.is_word = False
        

class StreamChecker:

    def __init__(self, words: List[str]):
        self.prefix = \"\"
        self.trienode = TrieNode()

        for word in words:
            node = self.trienode
            for c in word[::-1]:
                if c not in node.nodes:
                    node.nodes[c] = TrieNode()
                node = node.nodes[c]
            node.is_word = True

    def query(self, letter: str) -> bool:
        self.prefix += letter

        node = self.trienode
        for c in self.prefix[::-1]:
            if c not in node.nodes:
                break
            node = node.nodes[c]
            if node.is_word:
                return True
        
        return False


class Trie:
    def __init__(self, end=False):
        self.child = dict()
        self.end = end

    def add(self, word, i=0):
        if i >= len(word):
            return
        if word[i] not in self.child:
            self.child[word[i]] = Trie()
        if i == len(word) - 1:
            self.child[word[i]].end = True
        self.child[word[i]].add(word, i + 1)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = Trie()
        for word in words:
            self.root.add(word[::-1])
        self.stream = ''

    def query(self, letter: str) -> bool:
        self.stream = letter + self.stream
        ptr = self.root
        for c in self.stream:
            if c in ptr.child:
                ptr = ptr.child[c]
                if ptr.end:
                    return True
            else:
                break
        return False

class TrieNode:
    def __init__(self):
        self.dict = defaultdict(TrieNode)
        self.word = False
        
class StreamChecker:
    

    def __init__(self, words: List[str]):
        self.root = TrieNode()
        self.prefix = ''
        
        for word in words:
            node = self.root
            
            for char in word[::-1]:
                node = node.dict[char]
            
            node.word = True

    def query(self, letter: str) -> bool:
        self.prefix += letter
        node = self.root
        
        for char in self.prefix[::-1]:
            if char not in node.dict:
                break
            
            node = node.dict[char]
            
            if node.word == True:
                return True
        
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.data = collections.defaultdict(TrieNode)
        self.isWord = False
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.rec = collections.defaultdict(set)
        self.maxsize = float('-inf')
        self.minsize = float('inf')
        self.root = TrieNode()
        for w in words:
            self.maxsize = max(len(w), self.maxsize)
            self.minsize = min(len(w), self.minsize)
            curr = self.root
            for c in w[::-1]:
                curr = curr.data[c]
            
            curr.isWord = True

        self.curr = \"\"

    def query(self, letter: str) -> bool:
        
        self.curr += letter        
        #self.curr = self.curr[-self.maxsize:]
        
        curr = self.root
        for c in self.curr[::-1]:
            if c in curr.data:
                curr = curr.data[c]
                if curr.isWord:
                    return True
            else:
                return False
            
        return False
            
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.s = \"\"
        for w in words:
            node = self.trie
            for c in w[::-1]:
                if c not in node:
                    node[c] = {}
                node = node[c]
            node['#'] = True

    def query(self, letter: str) -> bool:
        self.s = letter+self.s
        node = self.trie
        for c in self.s:
            if c in node:
                node = node[c]
            else:
                return False
            if '#' in node:
                return True
        
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.words = {word[-1]: [] for word in words}
        self.string = \"\"
        for word in words:
            self.words[word[-1]].append(word)
        

    def query(self, letter: str) -> bool:
        self.string += letter
        for word in self.words.get(letter, []):
            if self.string[-1*len(word):] == word:
                return True
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.queried_word = \"\"
        self.dict_sets = defaultdict(lambda: set()) 
        for word in words:
            self.dict_sets[word[-1]].add(word)

    def query(self, letter: str) -> bool:
        self.queried_word += letter
        for word in self.dict_sets[letter]:
            if word == self.queried_word[-len(word):]:
                return True
        return False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.s = ''
        self.dic = collections.defaultdict(set)
        for w in words:
            self.dic[w[-1]].add(w)
                

    def query(self, letter: str) -> bool:
        self.s += letter
        return any(self.s.endswith(w) for w in self.dic[letter])


class trie_node:
    def __init__(self):
        self.d = dict()
        self.end = False
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = trie_node()
        self.l = \"\"
        for word in words:
            node = self.trie
            for c in word[::-1]:
                if c in node.d:
                    node = node.d[c]
                else:
                    temp = trie_node()
                    node.d[c] = temp
                    node = temp
            node.end = True

    def query(self, letter: str) -> bool:
        self.l += letter
        node = self.trie
        for c in self.l[::-1]:
            if c in node.d:
                node = node.d[c]
                if node.end:
                    return True
            else:
                return False
        
        return False
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

from collections import deque
class TreeNode:
    def __init__(self, val):
        self.val = val
        self.children = []
    def add_child(self, node):
        self.children.append(node)
        
class StreamChecker:
    def __init__(self, words: List[str]):
        self.root = TreeNode(0)
        self.max_len = 0
        for w in words:
            self.max_len = max(self.max_len, len(w))
            self.make_trie(w)
        self.history = deque([])
        
    def make_trie(self, word):
        parent = self.root
        for char in word[::-1]:
            current = None
            for node in parent.children:
                if node.val == char:
                    current = node
            if not current:
                current = TreeNode(char)
                parent.add_child(current)
            parent = current
        parent.add_child(TreeNode('.'))

    def query(self, letter: str) -> bool:
        self.history.append(letter)
        if len(self.history) > self.max_len:
            self.history.popleft()
        parent = self.root
        for i in range(len(self.history)-1, -1, -1):
            char = self.history[i]
            if i < len(self.history) - 1 and any([child.val == '.' for child in parent.children]):
                return True
            found = False
            for node in parent.children:
                if node.val == char:
                    found = True
                    parent = node
            if not found:
                return False
        return any([child.val == '.' for child in parent.children])
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.children = {}
        self.is_word = False

class StreamChecker:
    
    def __init__(self, words: List[str]):
    
        self.root = TrieNode()

        self.letterlist = \"\"

        for word in words:
            self._insert_word(word)
    
    def _insert_word(self, word):
        node = self.root
        
        for c in word[::-1]:
            if c not in node.children:
                node.children[c] = TrieNode()
            node = node.children[c]
        node.is_word = True    

    def query(self, letter: str) -> bool:
        self.letterlist += letter
        node = self.root
        k = 0
        
        for c in self.letterlist[::-1]:
            k += 1
            if c not in node.children:
                return False
            node=node.children[c]
            if k > 0 and node.is_word:
                return True
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:

    def __init__(self):
        self.is_leaf = False
        self.mp = {}

class StreamChecker:

    def __init__(self, words: List[str]):
        def insert(root, w):
            for c in w:
                if c not in root.mp:
                    root.mp[c] = TrieNode()
                root = root.mp[c]
            root.is_leaf = True
        self.root = TrieNode()
        for w in words:
            insert(self.root, w[::-1])
        self.s = ''
            
    def query(self, letter: str) -> bool:
        def find(root, s):
            for c in s[::-1]:
                if c not in root.mp: return False
                root = root.mp[c]
                if root.is_leaf: return True
            return False
        self.s += letter
        return find(self.root, self.s)        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


    
from typing import Tuple
from collections import deque

class TrieNode(object):
    \"\"\"
    Our trie node implementation. Very basic. but does the job
    \"\"\"

    def __init__(self, char: str):
        self.char = char
        self.children = []
        # Is it the last character of the word.`
        self.word_finished = False
        # How many times this character appeared in the addition process
        self.counter = 1


    def add(root, word: str):
        \"\"\"
        Adding a word in the trie structure
        \"\"\"
        node = root
        for char in word:
            found_in_child = False
            # Search for the character in the children of the present `node`
            for child in node.children:
                if child.char == char:
                    # We found it, increase the counter by 1 to keep track that another
                    # word has it as well
                    child.counter += 1
                    # And point the node to the child that contains this char
                    node = child
                    found_in_child = True
                    break
            # We did not find it so add a new chlid
            if not found_in_child:
                new_node = TrieNode(char)
                node.children.append(new_node)
                # And then point node to the new child
                node = new_node
        # Everything finished. Mark it as the end of a word.
        node.word_finished = True


    def find_prefix(root, prefix: str) -> Tuple[bool, int]:
        \"\"\"
        Check and return 
          1. If the prefix exsists in any of the words we added so far
          2. If yes then how may words actually have the prefix
        \"\"\"
        node = root
        # If the root node has no children, then return False.
        # Because it means we are trying to search in an empty trie
        if not root.children:
            return False, 0
        for char in prefix:
            char_not_found = True
            # Search through all the children of the present `node`
            for child in node.children:
                if child.char == char:
                    # We found the char existing in the child.
                    char_not_found = False
                    # Assign node as the child containing the char and break
                    node = child
                    break
            # Return False anyway when we did not find a char.
            if char_not_found:
                return False, 0
        # Well, we are here means we have found the prefix. Return true to indicate that
        # And also the counter of the last node. This indicates how many words have this
        # prefix
        return True, node.counter

class StreamChecker:

    
    def __init__(self, words: List[str]):
        self.d = deque()
        self.trie = TrieNode('*')
        self.wordMap = {}
        for word in words:
            self.wordMap[word[::-1]] = True
            self.trie.add(word[::-1])
    def query(self, letter: str) -> bool:
        self.d.appendleft(letter)
        s = \"\"
        for char in self.d:
            s += char
            val, counter = self.trie.find_prefix(s)
            if val and s in self.wordMap:
                return True
            if not val:
                return False
        return False

    
    

#so maybe manage pointers from recently read letters, if the current pointer from first read to #current is not in trie, move pointer from first to current.
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode():
    def __init__(self):
        self.is_word = False
        self.children = {}

class StreamChecker:

    def __init__(self, words: List[str]):
        self.stream = deque()
        self.root = TrieNode()
        
        for word in words:
            node = self.root
            for ch in word[::-1]:
                if ch not in node.children:
                    node.children[ch] = TrieNode()
                node = node.children[ch]
            node.is_word = True      

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        node = self.root
        
        for ch in self.stream:
            if ch not in node.children:
                return False
            node = node.children[ch]
            if node.is_word:
                return True
        
        return False
        
        
        

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import defaultdict as dd
class trieNode :
    def __init__(self) :
        self.children = dd(int)
        self.is_end = False
        
class trie :
    def __init__(self) :
        self.root = trieNode()
        
    def add(self,word) :
        
        par=self.root
        for char in word[::-1] :
            if par.children[char]==0 :
                par.children[char] = trieNode()
            par=par.children[char]
        par.is_end = True
        
    def check(self,s) :
        par=self.root
        for char in s[::-1] :
            if par.children[char] :
                par=par.children[char]
                if par.is_end :
                    return True
            
            else :
                return False
        return False
                
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = trie()
        self.cur = \"\"
        for word in words :
            self.trie.add(word)

    def query(self, letter: str) -> bool:
        self.cur+=letter
        if self.trie.check(self.cur) :
            return True
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:
    letter_queue = \"\"
    def __init__(self, words: List[str]):
        self.words_dict = {}
        for w in words:

            if w[-1] in self.words_dict:
                self.words_dict[w[-1]].add(w)
            else:
                self.words_dict[w[-1]] = set()
                self.words_dict[w[-1]].add(w)
        
    def query(self, letter: str) -> bool:
        self.letter_queue += letter
        if letter in self.words_dict:
            for item in self.words_dict[letter]:
                if item == self.letter_queue[-len(item):]: return True
     
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.word = ''
        self.dic = collections.defaultdict(set)
        for i in words:
            self.dic[i[-1]].add(i)
        
    def query(self, letter: str) -> bool:
        self.word += letter
        return any(self.word.endswith(i) for i in self.dic[letter])
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.s = ''
        self.d = collections.defaultdict(set)
        
        for word in words:
            self.d[word[-1]].add(word)

    def query(self, letter: str) -> bool:
        self.s += letter
        return any(self.s.endswith(w) for w in self.d[letter])


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    
    def __init__(self, val  =   \"\"):
        self.val    =   val;
        self.next_chars =   collections.defaultdict(str);
        self.end_of_word    =   False;
        return;

class Trie:
    
    def __init__(self, words):
        self.head       =   TrieNode(\"head\");
        
        for w in words:
            self._add_word(w[::-1]);
            
        return;
    
    def check_word(self, word):
        
        ptr =   self.head;
        for c in word[::-1]:
            
            if c not in ptr.next_chars:     return False;            
            
            ptr =   ptr.next_chars[c];
            
            if ptr.end_of_word:           return True;
            
        
        return ptr.end_of_word;
        
        
    def _add_word(self, word):
        
        ptr =   self.head;
        
        for c in word:
            
            if c not in ptr.next_chars:
                ptr.next_chars[c]   =   TrieNode(c);
            
            ptr =   ptr.next_chars[c];
        
        ptr.end_of_word =   True;
        
        return;

MAX_LENGTH  =   2001;

class StreamChecker:
    
    def __init__(self, words: List[str]):
        
        self.trie_words =   Trie(words);
        self.rolling_word   =   [];
        return;
        

    def query(self, letter: str) -> bool:
        
        self.rolling_word.append(   letter);
        
        result  =   self.trie_words.check_word( self.rolling_word);
            
        
        if len(self.rolling_word) >= MAX_LENGTH:    self.rolling_word.pop(0);
        
        return result;
    
    
    
    \"\"\"
    ############## BRUTE FORCE ##############################
    def __init__    (self, words):
        
        self.last_char_words    =   collections.defaultdict(set);
        self.rolling_word       =   \"\";
        
        for w in words:
            last_c  =   w[-1];
            self.last_char_words.setdefault(last_c, set()).add(w);
        
        #print(self.last_char_words);
        return;
    
    def query(  self, letter:str)   -> bool:
        
        self.rolling_word += letter;
        
        for w in self.last_char_words[letter]:
            ln_w    =   len(w);
            
            if self.rolling_word[-ln_w:] == w:
                return True;
        
        self.rolling_word   =   self.rolling_word[-MAX_LENGTH:];
        return False;
    \"\"\"
    


    


        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Node:
    def __init__(self):
        self.isLast = False
        self.child = {}


class Trie:
    def __init__(self):
        self.root = Node()
        
    def insert(self, ind, word, node = None):
        if node == None:
            node = self.root
        if ind == len(word):
            node.isLast = True
        else:
        # print(word)
            if word[ind] not in node.child:
                node.child[word[ind]] = Node()
            self.insert(ind+1,word,node.child[word[ind]])
            
    
    def isPrefix(self, ind, word, node = None):
        if node == None:
            node = self.root
        
        if node.isLast: return True
        
        if ind == len(word): return False
        
        if word[ind] in node.child:
            return self.isPrefix(ind+1, word, node.child[word[ind]])
        return False
        
        
        
from collections import deque

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        for word in words:
            self.trie.insert(0,word[::-1])
        
        self.stream = deque()
        

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        return self.trie.isPrefix(0, self.stream)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Node:
    def __init__(self):
        self.children = [None]*26
        self.isWord = False
    def calculateIndex(self,char):
        return ord(char)-ord('a')

class Trie:
    def __init__(self):
        self.root = Node()
    def addWordInReverse(self,word):
        wordLength = len(word)
        currentNode = self.root
        for i in range(wordLength-1,-1,-1):
            currentChar = word[i]
            currentIndex = currentNode.calculateIndex(currentChar)
            if(currentNode.children[currentIndex] == None):
                currentNode.children[currentIndex] = Node()
            currentNode = currentNode.children[currentIndex]
        currentNode.isWord = True;
class StreamChecker:

    def __init__(self, words: List[str]):
        self.stream = []
        self.reverseTrie = Trie()##no new keyword before object instantiation
        for word in words:
            self.reverseTrie.addWordInReverse(word)

    def query(self, letter: str) -> bool:
        self.stream.append(letter)
        streamLength = len(self.stream)
        currentNode = self.reverseTrie.root
        for i in range(streamLength-1,-1,-1):
            currentChar = self.stream[i]
            currentIndex = currentNode.calculateIndex(currentChar)
            if(currentNode.children[currentIndex] != None):
                currentNode = currentNode.children[currentIndex]
                if(currentNode.isWord):
                    return True
            else:
                return False
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.s = ''
        self.dic = collections.defaultdict(set)
        for w in words:
            self.dic[w[-1]].add(w)
                

    def query(self, letter: str) -> bool:
        self.s += letter
        return any(self.s.endswith(w) for w in self.dic[letter])

class Trie:
    def __init__(self):
        self.children = {}
        self.endSymbol = '*'
    
    def insert(self, word):
        children = self.children
        for char in word[::-1]:
            if char not in children:
                children[char] = {}
            children = children[char]
        children[self.endSymbol] = word
    
    
class StreamChecker:
    # O(n * m) Time | O(max(n, m)) Space
    # n: number of queries | m: length of longest word
    def __init__(self, words: List[str]):
        self.trie = Trie()
        for word in words:
            self.trie.insert(word)
        self.array = []

    def query(self, letter: str) -> bool:
        self.array.insert(0, letter)
        nodes = self.trie.children
        for char in self.array:
            if self.trie.endSymbol in nodes:
                return True
            if char not in nodes:
                return False
            nodes = nodes[char]
        return self.trie.endSymbol in nodes

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = dict()
        self.stream = deque([])
        for word in words:
            node = self.trie
            for ch in word[::-1]:
                node = node.setdefault(ch, {})
            node['end'] = True
    
    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        node = self.trie
        for ch in self.stream:
            if 'end' in node:
                return True
            if ch not in node:
                return False
            node = node[ch]
        return 'end' in node


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.query_letters = []
        # post-fix hash table
        self.hash = {}
        for w in words:
            for i in range(len(w)-1, -1, -1):
                if i == 0: self.hash[w[i:]] = True
                elif w[i:] in self.hash: continue
                else: self.hash[w[i:]] = False
        # print(self.hash)

    def query(self, letter: str) -> bool:
        self.query_letters.append(letter)
        length = len(self.query_letters)
        for i in range(length-1, -1, -1):
            ls = \"\".join(self.query_letters[i:])
            if ls not in self.hash: 
                return False
            if self.hash[ls]: return True
        return False


#     def __init__(self, words: List[str]):
#         self.Trie={}
#         for word in words:
#             curnode=self.Trie
#             word=word[::-1]
#             print(word)
#             for ch in word:
#                 if ch not in curnode:
#                     curnode[ch]={}
#                 curnode=curnode[ch]
#             curnode['#']=1 # '#' means the end of a word
#         self.pre=''
 
#     def query(self, letter: str) -> bool:
#         self.pre=self.pre+letter
#         curnode=self.Trie
#         print(curnode)
#         # print(self.pre)
#         for i in range(0,len(self.pre)):
#             if self.pre[-i-1] not in curnode:
#                 break
#             curnode=curnode[self.pre[-i-1]]
#             print(curnode)
#             if '#' in curnode:
#                 return True
#         return False

        

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Trie:
    def __init__(self):
        self.child = {}
        self.isEnd = False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = Trie()
        self.str = []
        
        for word in words:
            node = self.root
            for ch in reversed(word):
                if ch not in node.child:
                    node.child[ch] = Trie()
                node = node.child[ch]
            node.isEnd = True

    def query(self, letter: str) -> bool:
        self.str.insert(0, letter)
        
        node = self.root
        for ch in self.str:
            if ch not in node.child:
                return False
            node = node.child[ch]
            if node.isEnd:
                return True
        
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    def __init__(self):
        self.children = {}
        self.isEnd = False
    
    def insert(self, word):
        if len(word)==0:
            self.isEnd = True
            return
        if word[0] not in self.children:
            self.children[word[0]] = Trie()
        self.children[word[0]].insert(word[1:])
        
    def search(self, word):
        if len(word)==0:
            return (True, False)
        if len(word)==1:
            return (word[0] in self.children, word[0] in self.children and self.children[word[0]].isEnd)
        startsWith = word[0] in self.children
        if startsWith:
            return self.children[word[0]].search(word[1:])

        return (False, False)

    def startsWith(self, word):
        if len(word)==0:
            return True
        return word[0] in self.children and self.children[word[0]].startsWith(word[1:])
    def next(self, char):
        if char in self.children:
            return self.children[char]
        return None
    def printNode(self):
        print(self.children,self.isEnd)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.words = Trie()
        for word in words:
            self.words.insert(word[::-1])
        self.stream = \"\"

    def query(self, letter: str) -> bool:
        self.stream += letter
        node = self.words
        for i in range(len(self.stream)-1, -1, -1):
            node = node.next(self.stream[i])
            if node==None:
                return False
            if node.isEnd:
                return True
            
                
        return False

from collections import deque

class TrieNode:
    def __init__(self, val):
        # self.val = val
        self.end = False
        self.children = {}
        
class Trie:
    
    def __init__(self):
        self.root = TrieNode(-1)
    
    def add(self, word):
        root = self.root
        for idx, ch in enumerate(word):
            children = root.children
            if children.get(ch) == None:
                child = TrieNode(ch)
                children[ch] = child
                root = child
            else:
                root = children[ch]
                
            if idx == len(word)-1:
                root.end = True
    
    def search(self, word):

        root = self.root
        for idx, val in enumerate(word):
            if root.children.get(val) == None:
                return False
            else:
                root = root.children[val]
                if root.end:
                    return True
            if idx == len(word)-1 and root.end:
                return True
        
class StreamChecker:

    def __init__(self, words: List[str]):
        # self.words = set(words)
        self.Trie = Trie()
        self.maxlen = -1
        for w in words:
            # add word to Trie
            self.maxlen = max(self.maxlen, len(w))
            rev = w[::-1]
            self.Trie.add(rev)
        self.searchArr = deque()
        

    def query(self, letter: str) -> bool:

        self.searchArr.insert(0, letter)
        if len(self.searchArr) > self.maxlen:
            self.searchArr.pop()

        tmpWord = \"\".join(self.searchArr)    
        if self.Trie.search(tmpWord):
            return True        

        return False    
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            node = self.trie # reset for each word
            for ch in reversed(word):
                node.setdefault(ch, {})
                node = node[ch]
            node['#'] = {}
        self.letters = []

    def query(self, letter: str) -> bool:
        self.letters.insert(0, letter)
        node = self.trie
        for ch in self.letters:
            if ch in node:
                node = node[ch]
                if '#' in node:  # found it, no need to go deeper
                    return True
            else:
                break  # use the last found node
        return False

class StreamChecker:
    
    class Trie_node:
        def __init__(self,value):
            self.value = value
            self.children = {}
        
        def add_child(self,node,letter):
            self.children[letter] = node
        
        def is_child(self,letter):
            if letter in self.children:
                return True
            return False
        def get_child(self,letter):
            return self.children[letter]
        
    def __init__(self, words: List[str]):
        self.trie = self.Trie_node(-1)
        self.max_length = 0
        self.letter_list =[]
        for word in words:
            current_node = self.trie
            self.max_length = self.max_length if len(word) < self.max_length else len(word)
            
            for index,letter in enumerate(word[::-1]):
                if(current_node.is_child(letter)):
                    if(index == len(word)-1):
                        current_node.get_child(letter).value = 0
                else:
                    if(index == len(word)-1):
                        current_node.add_child(self.Trie_node(0),letter)
                    else:
                        current_node.add_child(self.Trie_node(-1),letter)
                current_node = current_node.get_child(letter)
        print((self.trie.children))
        

    def query(self, letter: str) -> bool:
        self.letter_list.append(letter)
        if(len(self.letter_list)>self.max_length):
            self.letter_list.pop(0)
        top_node = self.trie
        for letter in self.letter_list[::-1]:
            if(top_node.is_child(letter)):
                top_node = top_node.get_child(letter)
                if(top_node.value == 0):
                    return True
            else:
                return False
        return False
                    
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.stream = \"\"
        self.dictionary = {}
        for word in words:
            location = self.dictionary
            for char in word[::-1]:
                if char not in location:
                    location[char] = {}
                location = location[char]
            location[\"goodbye\"] = True

    def query(self, letter: str) -> bool:
        self.stream += letter
        count = -1
        location = self.dictionary
        for char in self.stream[::-1]:
            if char in location:
                location = location[char]
                if \"goodbye\" in location:
                    return True
                continue
            return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:
    def __init__(self, words: List[str]):
        self.words = set(words)
        self.letters = ''
        self.fragments = {}
        for w in words:
            temp = self.fragments
            for i in range(len(w)):
                sec = w[len(w)-1-i:]
                if sec not in temp:
                    temp[sec] = {}
                temp = temp[sec]
                    
    def query(self, letter: str) -> bool:
        self.letters += letter
        chars = self.letters
        
        temp = self.fragments
        for i in range(len(chars)):
            sec = chars[len(chars) - 1 - i:]
            if sec not in temp:
                return False
            temp = temp[sec]
            if sec in self.words:
                return True
        
    '''
    def __init__(self, words: List[str]):
        self.words = tuple(words)
        self.letters = ''
        
    def query(self, letter: str) -> bool:
        self.letters +=letter
        return self.letters.endswith(self.words)        
    '''
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    def __init__(self, c: str = None):
        self.c = c
        self.ch = [None] * 26
        self.isEnd = False
    
    def insert(self, word: List[str], idx: int = None):
        # print(\"start\", self)
        if idx is None:
            idx = len(word) - 1        
        if idx == -1:
            self.isEnd = True
            # print(\"insert to end\", self)            
            return
        c = ord(word[idx]) - ord('a')
        if self.ch[c] is None:
            self.ch[c] = Trie(word[idx])
        self.ch[c].insert(word, idx-1)
        # print(self)        
    
    def __str__(self):
        out = []
        for i in range(26):
            if self.ch[i] is None:
                continue
            out.append(chr(i + ord('a')) + \"{%r}\"%(str(self.ch[i])))
        return \"[%r,%r] \"%(self.c, self.isEnd) + \" \".join(out)
            
        
    def query(self, word: List[str], idx: int = None):
        if self.isEnd:
            return True
        if idx is None:
            idx = len(word) - 1
        if idx == -1:
            return self.isEnd
        c = ord(word[idx]) - ord('a')
        if self.ch[c] is None:
            return False
        return self.ch[c].query(word, idx-1)
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = Trie(\"*\")
        maxLen = 0
        for w in words:
            wli = [c for c in w]
            self.root.insert(wli)
            maxLen = max(maxLen, len(wli))
        self.maxLen = maxLen
        self.buf = []
        # print(\"final \", str(self.root))

    def query(self, letter: str) -> bool:
        self.buf.append(letter)
        return self.root.query(self.buf)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.s = ''
        self.dic = collections.defaultdict(set)
        for w in words:
            self.dic[w[-1]].add(w)
                

    def query(self, letter: str) -> bool:
        self.s += letter
        return any(self.s.endswith(w) for w in self.dic[letter])

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.children = defaultdict(TrieNode)
        self.is_end = False
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = TrieNode()
        self.s = []
        for word in words:
            current = self.root
            for w in reversed(word):
                current = current.children[w]
            current.is_end = True

    def query(self, letter: str) -> bool:
        self.s.append(letter)
        current = self.root
        for w in reversed(self.s):
            if w not in current.children:
                break
            current = current.children[w]
            if current.is_end:
                return True
        return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import deque

class TrieNode:
    
    def __init__(self, word:str) -> None:
        self.children = {}
        self.exist = False
        
        if word is not None:
            self.add(word)
            
    def __repr__(self) -> str:
        return \"{\" + \", \".join([f\"{x}: {self.children[x]}\" for x in self.children]) + \"}\"
        
    def add(self, word: str) -> None:
        if word == \"\":
            self.exist = True
            return 
        if word[0] not in self.children:
            self.children[word[0]] = TrieNode(word[1:])
        else:
            self.children[word[0]].add(word[1:])
        return
    
    def get_child(self, word: str):
        if word == \"\":
            return self
        if word[0] in self.children:
            return self.children[word[0]].get_child(word[1:])
        return None
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = TrieNode(None)
        
        max_word_len = 0
        for word in words:
            self.root.add(word[::-1])
            max_word_len = max(max_word_len, len(word))
        
        self.stream = deque(maxlen=max_word_len)
        
    def query(self, letter: str) -> bool:
        self.stream.append(letter)
        
        prefix = list(self.stream)[::-1]
        curr_node = self.root
        for char in prefix:
            if char in curr_node.children:
                if curr_node.children[char].exist == True:
                    return True
                curr_node = curr_node.children[char]
            else:
                return False
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self, val):
        self.val = val
        self.isEnd = False
        self.children = dict()
        

class Trie:
    def __init__(self):
        self.root = TrieNode(None)

    def insert(self, word):
        i = 0
        curr = self.root
        while i < len(word):
            if word[i] not in curr.children:
                curr.children[word[i]] = TrieNode(word[i])
            curr = curr.children[word[i]]
            i += 1
        curr.isEnd = True
    
    def exists(self, stream):
        def solve(node, i):
            if i < 0 or stream[i] != node.val:
                return False
            elif node.val == stream[i] and node.isEnd:
                return True
            for key, val in node.children.items():
                if solve(val, i-1):
                    return True
            return False
        return any([solve(child, len(stream) - 1) for child in self.root.children.values()])

    def dfs(self):
        def solve(node, lvl):
            for child in node.children.values():
                solve(child, lvl+1)
        solve(self.root, 0)
        
        

class StreamChecker:
    def __init__(self, words: List[str]):
        self.stream = []
        self.trie = Trie()
        for word in words:
            self.trie.insert(word[::-1])        
        self.trie.dfs()

        
    def query(self, letter: str) -> bool:
        self.stream.append(letter)
        return self.trie.exists(self.stream)
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


'''
cd, f, kl

             _
            / \\  \\
            d  f  l
            |     |k
            c

O(max len of words)
O(2000) = O(1) lookup

'''

class StreamChecker:

    def __init__(self, words: List[str]):
        self.s = ''
        self.dic={}
        for word in words:
            try:
                if self.dic[word[-1]]==1:
                    pass
                self.dic[word[-1]].append(word)
            except:
                self.dic[word[-1]]=[word,]

    def query(self, letter: str) -> bool:
        self.s += letter
        ans=False
        try:
            for w in self.dic[letter]:
                if self.s.endswith(w):
                    ans=True
        except:
            pass
        return ans


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import defaultdict
class StreamChecker:

    def __init__(self, words: List[str]):
        self.dictionary = defaultdict(list)
        for word in words:
            self.dictionary[word[-1]].append(word[:-1])
        
        self.pastQueries = \"\"
        
    def query(self, letter: str) -> bool:
        self.pastQueries += letter
        if letter in self.dictionary:
            for word in self.dictionary[letter]:
                complete_word = word + letter
                length = len(complete_word)
                if len(self.pastQueries) >= length and complete_word == self.pastQueries[- length:]:
                    return True
            return False
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Trie:
    def __init__(self):
        self.trie = {}
    
    def add(self, word):
        trie = self.trie
        for c in word[::-1]:
            trie = trie.setdefault(c, {})
        trie[\"eos\"] = {}
        
    def find(self, char_list):
        trie = self.trie
        for c in char_list:
            if c not in trie.keys():
                return False
            trie = trie[c]
            if \"eos\" in trie.keys():
                return True
        return False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.query_list = []
        self.trie = Trie()
        for word in words:
            self.trie.add(word)

    def query(self, letter: str) -> bool:
        self.query_list.insert(0, letter)
        return self.trie.find(self.query_list)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:
    
    class TrieNode:
        def __init__(self):
            self.children = {}
            self.endOfWord = False

    def __init__(self, words: List[str]):
        self.root = self.TrieNode()
        self.stream = []
        
        for word in words:
            node = self.root
            for char in word[::-1]:
                if char not in node.children:
                    node.children[char] = self.TrieNode()
                node = node.children[char]
            node.endOfWord = True
       
    
    def query(self, letter: str) -> bool:
        node = self.root
        self.stream.insert(0,letter)
        for char in self.stream:
            if char not in node.children:
                return False
            node = node.children[char]
            if node.endOfWord == True:
                return True
                break
                
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
    letter_queue = \"\"
    def __init__(self, words: List[str]):
        self.words_dict = {}
        for w in words:

            if w[-1] in self.words_dict:
                self.words_dict[w[-1]].add(w)
            else:
                self.words_dict[w[-1]] = set()
                self.words_dict[w[-1]].add(w)
        print(self.words_dict)
        
    def query(self, letter: str) -> bool:
        self.letter_queue += letter
        if letter in self.words_dict:
            for item in self.words_dict[letter]:
                # b = False
                l = len(item)
                if item == self.letter_queue[-l:]:
                    return True
                # if not b: return True
        
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.s = ''
        self.dic = collections.defaultdict(set)
        for w in words:
            self.dic[w[-1]].add(w)
                

    def query(self, letter: str) -> bool:
        self.s += letter
        return any(self.s.endswith(w) for w in self.dic[letter])        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class trie:
    def __init__(self,val=None):
        self.val = val
        self.next = {}
        self.is_complete = False
    
'''
### https://youtu.be/Y37WA4advWw

Logic here is to make trie of given works in reverse order ..so that if we want to find whether upto this point any query make sense...we can check in reverse order

'''
class StreamChecker:
    
    def __init__(self, words: List[str]):
        self.root = trie()
        ### insert all words in trie
        for w in words:
            node=self.root
            for c in w[::-1]:
                if c not in node.__next__:
                    node.next[c] = trie(c)
                node=node.next[c]
            node.is_complete=True
        
        ###to keep track of previous queries
        self.queries = []
        
        
        
    def query(self, letter: str) -> bool:
        self.queries.insert(0,letter)
        
        ### search in trie
        node = self.root
        for c in self.queries:
            if c not in node.__next__:
                return False
            node=node.next[c]
            if node.is_complete:
                return True
            
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.tab = collections.defaultdict(set)
        for w in words:
            self.tab[w[-1]].add(w)
            
        self.queried = ''
        

    def query(self, letter: str) -> bool:
        self.queried += letter
        if letter not in self.tab:
            return False
        candidates = self.tab[letter]
        for can in candidates:
            if can == self.queried[-len(can):]:
                return True
        return False
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.children = {}
        self.terminal = False
        
class StreamChecker:

    def __init__(self, words: List[str]):
        
        def addword(word):
            node = self.root
            for char in reversed(word):
                if char not in node.children:
                    node.children[char] = TrieNode()
                node = node.children[char]
            node.terminal = True
        
        self.array = []
        self.root = TrieNode()
        for word in words:
            addword(word)

    def query(self, letter: str) -> bool:
        
        array = self.array
        node = self.root
        array.append(letter)
        
        for char in reversed(array):
            if char in node.children:
                node = node.children[char]
                if node.terminal: return True
            else:
                return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    def __init__(self):
        self.child = {}
        self.isEnd = False
class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = Trie()
        self.str = []
        
        for word in words:
            node = self.root
            for ch in reversed(word) :
                if ch not in node.child:
                    node.child[ch] = Trie()
                node = node.child[ch]
            node.isEnd = True
    def query(self, letter: str) -> bool:
        self.str.insert(0, letter)
        
        node = self.root
        for ch in self.str:
            if ch not in node.child:
                return False
            node = node.child[ch]
            if node.isEnd:
                return True
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    def __init__(self):
        self.children = {}
        self.endSymbol = '*'
    
    def insert(self, word):
        children = self.children
        for char in word[::-1]:
            if char not in children:
                children[char] = {}
            children = children[char]
        children[self.endSymbol] = word
    
    
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        for word in words:
            self.trie.insert(word)
        self.array = []

    def query(self, letter: str) -> bool:
        self.array.insert(0, letter)
        nodes = self.trie.children
        for char in self.array:
            if self.trie.endSymbol in nodes:
                return True
            if char not in nodes:
                return False
            nodes = nodes[char]
        return self.trie.endSymbol in nodes

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
    def __init__(self,words:List[str]):
        self.s,self.dic='',collections.defaultdict(set)
        for i in words:self.dic[i[-1]].add(i)
    def query(self,letter:str)->bool:
        self.s+=letter
        return any(self.s.endswith(i) for i in self.dic[letter])

class Node:
    def __init__(self):
        self.children = {}
        self.is_start = False

class StreamChecker:
    from collections import defaultdict
    
    
    def __init__(self, words: List[str]):
        self.queries = \"\"
        self.root = Node()
        self.found = False
        for word in words:
            r = self.root
            for ch in reversed(word):
                if r.children.get(ch,None):
                    r = r.children[ch]
                else:
                    n = Node()
                    r.children[ch] = n
                    r = n
            r.is_start = True
            
    def dfs(self):
        def dfs_util(node, str_):
            if not str_:
                return
            n = node.children.get(str_[0],None)
            if not n:
                return
            if n.is_start:
                self.found = True
            dfs_util(n, str_[1:])
            return
        dfs_util(self.root, self.queries)
            
            
        
        

    def query(self, letter: str) -> bool:
        self.queries = letter + self.queries
        #print(self.queries)
        self.found = False
        self.dfs()
        return self.found
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

import string
class Node :
    def __init__(self):
        self.characters={}
        self.isEnd=False
class Trie :
    def __init__(self):
        self.root=None
    def insert(self,word):
        if self.root==None :
            self.root=Node()
        curr_node=self.root
        #print(curr_node.isEnd)
        n=len(word)
        i=0
        while i < n :
            #print(i)
            if word[i] not in curr_node.characters :
                node=Node()
                curr_node.characters[word[i]]=node
            curr_node=curr_node.characters[word[i]]
            if i==n-1 :
                curr_node.isEnd=True
            i+=1
            
    def print_words(self) :
        node=self.root
        q=[(node,\"\")]
        while len(q) > 0 :
            node,word=q.pop(0)
            if node.isEnd==True :
                print(word)
            for ch in node.characters :
                q.append((node.characters[ch],word+ch))
    def search(self, word: str) -> bool:
        \"\"\"
        Returns if the word is in the trie.
        \"\"\"
        if self.root==None :
            return False
        current_node=self.root
        current_index=0
        n=len(word)
        while current_index < n :
            if word[current_index] not in current_node.characters :
                return False
            current_node=current_node.characters[word[current_index]]
            current_index+=1
            if current_node.isEnd==True :
                return True
        return False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie=Trie()
        for word in words :
            #print(word[::-1])
            self.trie.insert(word[::-1])
        self.curr_string=\"\"
        #self.trie.print_words()

    def query(self, letter: str) -> bool:
        self.curr_string+=letter
        #print(self.curr_string[::-1])
        return self.trie.search(self.curr_string[::-1])
        # n=len(self.curr_string)
        # for i in range(n-1,-1,-1) :
        #     if self.trie.search(self.curr_string[i:n]) ==True :
        #         return True
        # return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.dic = {}
        for word in words:
            if word[-1] not in self.dic:
                self.dic[word[-1]] = [word[:-1]]
            else:
                self.dic[word[-1]].append(word[:-1])
        
        self.string = \"\"

    def query(self, letter: str) -> bool:
        self.string += letter
        if letter in self.dic:
            for word in self.dic[letter]:
                length = len(word) + 1
                complete_word = word + letter
                if len(self.string) >= length and complete_word == self.string[- length:]:
                    return True
            return False
        else:
            return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:
    
    def char_int(self, char):
        return ord(char)-ord('a')
    
    def add_trie(self, trie, word, idx):
        if idx == len(word):
            trie[26] = True
            return
        idx_trie = self.char_int(word[idx])
        if not trie[idx_trie]:
            trie[idx_trie] = [None]*27
        self.add_trie(trie[idx_trie], word, idx+1)
        
    
        

    def __init__(self, words: List[str]):
        self.trie = [None]*27
        for word in words:
            self.add_trie(self.trie, word[::-1], 0)
        
        self.str = []

    def query(self, letter: str) -> bool:
        self.str.append(letter)
        i = len(self.str)-1
        trie = self.trie
        while i >= 0 and trie:
            t = trie[:]
            for j in range(len(t)):
                if t[j]:
                    t[j] = chr(ord('a')+j)
            if trie[26]:
                return True
            trie = trie[self.char_int(self.str[i])]
            i -= 1
        if trie and trie[26]:
            return True
    
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


#
# @lc app=leetcode id=1032 lang=python3
#
# [1032] Stream of Characters
#
# https://leetcode.com/problems/stream-of-characters/description/
#
# algorithms
# Hard (35.61%)
# Total Accepted:    2.4K
# Total Submissions: 6.6K
# Testcase Example:  '[\"StreamChecker\",\"query\",\"query\",\"query\",\"query\",\"query\",\"query\",\"query\",\"query\",\"query\",\"query\",\"query\",\"query\"]\
[[[\"cd\",\"f\",\"kl\"]],[\"a\"],[\"b\"],[\"c\"],[\"d\"],[\"e\"],[\"f\"],[\"g\"],[\"h\"],[\"i\"],[\"j\"],[\"k\"],[\"l\"]]'
#
# Implement the StreamChecker class as follows:
#
#
# StreamChecker(words): Constructor, init the data structure with the given
# words.
# query(letter): returns true if and only if for some k >= 1, the last k
# characters queried (in order from oldest to newest, including this letter
# just queried) spell one of the words in the given list.
#
#
#
#
# Example:
#
#
# StreamChecker streamChecker = new StreamChecker([\"cd\",\"f\",\"kl\"]); // init the
# dictionary.
# streamChecker.query('a');          // return false
# streamChecker.query('b');          // return false
# streamChecker.query('c');          // return false
# streamChecker.query('d');          // return true, because 'cd' is in the
# wordlist
# streamChecker.query('e');          // return false
# streamChecker.query('f');          // return true, because 'f' is in the
# wordlist
# streamChecker.query('g');          // return false
# streamChecker.query('h');          // return false
# streamChecker.query('i');          // return false
# streamChecker.query('j');          // return false
# streamChecker.query('k');          // return false
# streamChecker.query('l');          // return true, because 'kl' is in the
# wordlist
#
#
#
#
# Note:
#
#
# 1 <= words.length <= 2000
# 1 <= words[i].length <= 2000
# Words will only consist of lowercase English letters.
# Queries will only consist of lowercase English letters.
# The number of queries is at most 40000.
#
#
#
import collections


class StreamChecker:
    def __init__(self, words):
        self.dic = collections.defaultdict(set)
        self.s = ''
        for w in words:
            self.dic[w[-1]].add(w)

    def query(self, letter):
        self.s += letter
        return any(self.s.endswith(w) for w in self.dic[letter])


# Your StreamChecker object will be instantiated and called as such:
words = [\"cd\", \"f\", \"kl\"]
obj = StreamChecker(words)
for i in range(ord('a'), ord('l') + 1):
    letter = chr(i)

# param_1 = obj.query(letter)



                
class StreamChecker:

    def __init__(self, words: List[str]):
        self.dic = {}
        for word in words:
            if word[-1] not in self.dic:
                self.dic[word[-1]] = [word[:-1]]
            else:
                self.dic[word[-1]].append(word[:-1])
        
        self.string = \"\"

    def query(self, letter: str) -> bool:
        self.string += letter
        if letter in self.dic:
            for word in self.dic[letter]:
                length = len(word) + 1
                complete_word = word + letter
                if len(self.string) >= length and complete_word == self.string[- length:]:
                    return True
            return False
        else:
            return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Trie:
    def __init__(self, words: List[str]):
        self.trie = lambda: collections.defaultdict(self.trie)
        self.root = self.trie()
        
        for w in words:
            self.add(w[::-1])
    
    def add(self, s: str):
        curr = self.root  
        for c in s:
            curr = curr[c]
        curr['#']

    def find(self, s: List[str]):
        curr = self.root
        for i in range(len(s) - 1, -1, -1):
            val = s[i]
            
            if '#' in curr: 
                return True
            elif val in curr: 
                curr = curr[val]
            else:
                return False
            
        return '#' in curr

#just use a trie bro
class StreamChecker:

    def __init__(self, words: List[str]):
        self.queries = []
        self.trie = Trie(words)
        
    def query(self, letter: str) -> bool:
        self.queries.append(letter)
        return self.trie.find(self.queries)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.dic = {}
        for word in words:
            if word[-1] not in self.dic:
                self.dic[word[-1]] = [word[:-1]]
            else:
                self.dic[word[-1]].append(word[:-1])
        
        self.string = \"\"

    def query(self, letter: str) -> bool:
        self.string += letter
        if letter in self.dic:
            for word in self.dic[letter]:
                length = len(word) + 1
                complete_word = word + letter
                if len(self.string) >= length and complete_word == self.string[- length:]:
                    return True
            return False
        else:
            return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

#Trie
class TrieNode:
    def __init__(self):
        self.children = {}
        self.isEnd = False
class Trie:
    def __init__(self):
        self.root = TrieNode()
        self.currentMatch = frozenset([self.root])
    def insert(self, word):
        cur = self.root
        for i in range(len(word)):
            idx = ord(word[i]) - ord('a')
            if idx not in cur.children:
                cur.children[idx] = TrieNode()
            cur = cur.children[idx]
        cur.isEnd = True
    @lru_cache(None)
    def matchNextChar(self, currentMatch, c):
        idx = ord(c) - ord('a')
        new_set = set([self.root])
        found = False
        for node in currentMatch:
            if idx in node.children:
                new_set.add(node.children[idx])
                if node.children[idx].isEnd:
                    found = True
        return frozenset(new_set), found
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        for word in words:
            self.trie.insert(word)
    def query(self, letter: str) -> bool:
        match, found = self.trie.matchNextChar(self.trie.currentMatch, letter)
        self.trie.currentMatch = match
        return found


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:

    def __init__(self):
        self._nodes = [None for _ in range(26)]
        self._isEnd = False

    def add(self, word, idx):
        if idx == len(word):
            self._isEnd = True
        else:
            char_id = ord(word[idx]) - ord('a')
            if self._nodes[char_id] is None:
                self._nodes[char_id] = TrieNode()
            self._nodes[char_id].add(word, idx+1)

    def query(self, word, idx):
        if self._isEnd is True:
            return True
        if idx == len(word):
            return False
        char_id = ord(word[idx]) - ord('a')
        if self._nodes[char_id] is None:
            return False
        return self._nodes[char_id].query(word, idx+1)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.node = TrieNode()
        self.letters = \"\"
        self.max_word_length = 0
        for word in words:
            self.max_word_length = max(self.max_word_length, len(word))
            self.node.add(word[::-1], 0)

    def query(self, letter: str) -> bool:
        self.letters = (letter + self.letters)[:self.max_word_length]
        return self.node.query(self.letters, 0)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class trieNode:
    def __init__(self):
        self.children = [None] * 26
        self.isWord = False

class trie:
    def __init__(self):
        self.root = trieNode()
    
    def insert_reverse(self, word):
        cp = self.root
        for i in range(len(word) - 1, -1, -1):
            index = ord(word[i]) - ord('a')
            if not cp.children[index]:
                cp.children[index] = trieNode()
            cp = cp.children[index]
        
        cp.isWord = True
    
    def search(self, word):
        cp = self.root
        for ch in word:
            index = ord(ch) - ord('a')
            if not cp.children[index]:
                return False
            if cp.children[index].isWord:
                return True
            cp = cp.children[index]
            
        return cp.isWord
    
class StreamChecker:

    def __init__(self, words: List[str]):
        self.tt = trie()
        self.str = \"\"
        self.maxlen = 0
        for w in words:
            self.tt.insert_reverse(w)
            self.maxlen = max(self.maxlen, len(w))
        
    def query(self, letter: str) -> bool:
        self.str += letter
        word = self.str[::-1]
        if self.maxlen < len(word):
            word = word[:self.maxlen]

        return self.tt.search(word)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker(object):

    def __init__(self, words):
        self.word_map, self.len_map, self.buffer = defaultdict(set), defaultdict(set), \"\"
        for w in words:
            self.word_map[w[-1]].add(w[::-1])
            self.len_map[w[-1]].add(len(w))
        

    def query(self, letter):
        self.buffer = letter + self.buffer
        return any(len(self.buffer) >= l and self.buffer[:l] in self.word_map[letter] for l in self.len_map[letter])


class StreamChecker:

    def __init__(self, words: List[str]):
        self.s = ''
        self.trie = Trie()
        for wrd in words:
            self.trie.insert(wrd[::-1])

    def query(self, letter: str) -> bool:
        self.s += letter
        node = self.trie.root
        for ch in self.s[::-1]:
            if ch in node.childs:
                node = node.childs[ch]
                if node.isWord:
                    return True
            else:
                break
        return False
        
class TrieNode:
    def __init__(self):
        self.childs = {}
        self.isWord = False

class Trie:
    def __init__(self):
        self.root = TrieNode()
    
    def insert(self, word):
        r = self.root
        for ch in word:
            r = r.childs.setdefault(ch, TrieNode())
        r.isWord = True
        
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    
    def __init__(self):
        
        self.nodes = {}
        self.is_word = False


class Trie:

    def __init__(self):
        self.root = TrieNode()

    def insert_word(self, word: str):
        root = self.root
        for c in word:
            root = root.nodes.setdefault(c, TrieNode())
        root.is_word = True

    def contains_substr(self, word: str):
        # Returns True if any beginning of word is contained in trie.
        root = self.root
        for c in word:
            if c not in root.nodes:
                break
            root = root.nodes[c]
            if root.is_word:
                return True
        return False


class StreamChecker:

    def __init__(self, words: List[str]):
        self.prefix = \"\"
        self.trie = Trie()

        for word in words:
            self.trie.insert_word(word[::-1])

    def query(self, letter: str) -> bool:
        self.prefix += letter
        return self.trie.contains_substr(self.prefix[::-1])

class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = Trie()
        self.letters = ''
        
        for word in words:
            self.insert(word)

    def query(self, letter: str) -> bool:
        self.letters += letter
        curr = self.root
        for i in range(len(self.letters)-1, -1, -1):
            if curr.child[ord(self.letters[i])-ord('a')] == None:
                return False
            curr = curr.child[ord(self.letters[i])-ord('a')]
            if curr.end:
                return True
        return False
    
    def insert(self, word):
        curr = self.root
        for i in range(len(word)-1, -1, -1):
            c = word[i]
            nextt = curr.child[ord(c)-ord('a')]
            if nextt == None:
                nextt = Trie()
                curr.child[ord(c)-ord('a')] = nextt
            curr = curr.child[ord(c)-ord('a')]
        curr.end = True
        

class Trie:
    def __init__(self):
        self.end = False
        self.child = [None for i in range(26)]

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.dic = {}
        
        for word in words:
            if word[-1] not in self.dic:
                self.dic[word[-1]] = [word[:-1]]
            else:
                self.dic[word[-1]].append(word[:-1])
        
        self.string = \"\"

    def query(self, letter: str) -> bool:
        self.string += letter
        if letter in self.dic:
            for word in self.dic[letter]:
                length = len(word) + 1
                complete_word = word + letter
                if len(self.string) >= length and complete_word == self.string[- length:]:
                    return True
        return False
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self):
        self.children = {}
        self.endNode = False
         
class Trie:
    def __init__(self):
        self.root = TrieNode()

    def insert(self, word):
        root = self.root
        for symbol in word:
            root = root.children.setdefault(symbol, TrieNode())
        root.endNode = True

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        #self.Stream = deque()
        self.Stream = \"\"
        for word in words:
            self.trie.insert(word[::-1])

    def query(self, letter: str) -> bool:
        #self.Stream.appendleft(letter)
        self.Stream += letter
        cur = self.trie.root
        for c in self.Stream[::-1]:
            if c in cur.children:
                cur = cur.children[c]
                if cur.endNode:
                    return True
            else: 
                break
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    
    def __init__(self):
        self.child = collections.defaultdict(TrieNode)
        self.is_end = False
        
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = TrieNode()
        self.last_k = collections.deque()
        self.k = max(len(word) for word in words)
        
        for word in words:
            self._insert(word[::-1])
            
    def _insert(self, word):
        curr = self.root
        for ch in word:
            curr = curr.child[ch]
        curr.is_end = True        

    def query(self, letter: str) -> bool:
        self.last_k.appendleft(letter)      
        if len(self.last_k) > self.k:   # maintain a window size of k
            self.last_k.pop()
        
        curr = self.root
        for ch in self.last_k:
            if ch not in curr.child:
                return False
            curr = curr.child[ch]
            if curr.is_end:
                return True
        return curr.is_end
        

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie(words)
        self.maxLen = len(max(words, key=lambda s: (len(s), s)))
        self.queue = deque([])
        
    def query(self, letter: str) -> bool:
        
        if len(self.queue) >= self.maxLen:
            self.queue.popleft()
            
        self.queue.append(letter)
        
        # for i in range(len(self.queue)-1, -1, -1):
        if self.trie.findWord(self.trie.store, len(self.queue)-1, ''.join(self.queue)):
            return True
            
        return False
            
        

class Trie:
    def __init__(self, words):
        self.store = {}
        for w in words:
            self.insertWord(self.store, len(w)-1, w)
        
    def insertWord(self, trie, p, w):
        if p < 0:
            return

        if w[p] not in trie:
            trie[w[p]] = {}
            
        self.insertWord(trie[w[p]], p-1, w)

        if p == 0:
            trie[w[p]]['$'] = True
            
    def findWord(self, trie, p, w):
        if p < 0 or w[p] not in trie:
            return False
        
        if '$' in trie[w[p]]:
            return True
        
        isAvail = False
        
        if w[p] in trie:
            isAvail = self.findWord(trie[w[p]], p-1, w)
        
        return isAvail
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Node:
    def __init__(self,c):
        self.c=c
        self.childs=[None for i in range(26)]
        self.end=False
class Trie:
    def __init__(self):
        self.root=None
        self.p=[]
        
    def insert(self,word):
        if(self.root==None):
            self.root=Node('#')
        r=self.root
        for i in word[::-1]:
            if(r.childs[ord(i)-97]==None):
                r.childs[ord(i)-97]=Node(i)
            r=r.childs[ord(i)-97]
        r.end=True
        
    def search(self,word):
        if(self.root==None):
            return False
        r=self.root
        for i in word[::-1]:
            if r.childs[ord(i)-97]!=None:
                r=r.childs[ord(i)-97]
            else:
                return False
            if(r.end):
                return True
        return False
    

class StreamChecker:

    def __init__(self, words: List[str]):
        self.tree=Trie()
        self.s=''
        for word in words:
            self.tree.insert(word)

    def query(self, letter: str) -> bool:
        self.s+=letter
        return self.tree.search(self.s)
    
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        
        self.wordSet=set(words)
        lSet=set()
        self.lastL=set()
        for word in words:
            lSet.add(len(word))
            self.lastL.add(word[-1])
        self.l=list(lSet)
        self.l.sort()
        self.q=''
        
    def query(self, letter: str) -> bool:
        self.q=self.q+letter
        
        if letter in self.lastL:
            for i in range(len(self.l)):
                if self.l[i]>len(self.q):
                    break
                elif self.q[-self.l[i]:] in self.wordSet:
                    return True
        return False
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.dic = {}
        for word in words:
            if word[-1] not in self.dic:
                self.dic[word[-1]] = [word[:-1]]
            else:
                self.dic[word[-1]].append(word[:-1])
        
        self.string = \"\"

    def query(self, letter: str) -> bool:
        self.string += letter
        if letter in self.dic:
            for word in self.dic[letter]:
                length = len(word) + 1
                complete_word = word + letter
                if len(self.string) >= length and complete_word == self.string[- length:]:
                    return True
            return False
        else:
            return False


class Trie():
    def __init__(self):
        self.isWord = False
        self.children = {}

class StreamChecker:

    def __init__(self, words: List[str]):
        self.StreamChecker = Trie()
        self.stack = []
        for word in words:
            self.insert(word)
        
    def query(self, letter: str) -> bool:
        self.stack.insert(0,letter)
        node = self.StreamChecker
        for char in self.stack:
            if node.isWord == True:
                return True
            if char not in node.children:
                return False
            node = node.children[char]
        if node.isWord == True:
            return True
        else:
            return False
    
    def insert(self, word):
        node = self.StreamChecker
        word = word[::-1]
        for letter in word:

            if letter not in node.children:
                node.children[letter] = Trie()
            node = node.children[letter]
        node.isWord = True
            

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import deque

class TrieNode:
    def __init__(self, val):
        self.end = False
        self.children = {}
        
class Trie:
    
    def __init__(self):
        self.root = TrieNode(-1)
    
    def add(self, word):
        root = self.root
        for idx, ch in enumerate(word):
            children = root.children
            if children.get(ch) == None:
                child = TrieNode(ch)
                children[ch] = child
                root = child
            else:
                root = children[ch]
                
            if idx == len(word)-1:
                root.end = True
    
    def search(self, word):

        root = self.root
        for idx, val in enumerate(word):
            if root.children.get(val) == None:
                return False
            else:
                root = root.children[val]
                if root.end:
                    return True
        
class StreamChecker:

    def __init__(self, words: List[str]):
        # self.words = set(words)
        self.Trie = Trie()
        self.maxlen = -1
        for w in words:
            self.maxlen = max(self.maxlen, len(w))
            rev = w[::-1]
            self.Trie.add(rev)
        self.searchArr = deque()
        

    def query(self, letter: str) -> bool:

        self.searchArr.insert(0, letter)
        if len(self.searchArr) > self.maxlen:
            self.searchArr.pop()

        tmpWord = \"\".join(self.searchArr)    
        return self.Trie.search(tmpWord)
#             return True        

#         return False    
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.dic = {}
        for word in words:
            if word[-1] not in self.dic:
                self.dic[word[-1]] = [word[:-1]]
            else:
                self.dic[word[-1]].append(word[:-1])
        
        self.string = \"\"

    def query(self, letter: str) -> bool:
        self.string += letter
        if letter in self.dic:
            for word in self.dic[letter]:
                length = len(word) + 1
                complete_word = word + letter
                if len(self.string) >= length and complete_word == self.string[- length:]:
                    return True
            return False
        else:
            return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.dict={}
        for word in words:
            if word[-1] not in self.dict:
                self.dict[word[-1]]=[word[:-1]]
            else:
                self.dict[word[-1]].append(word[:-1])
        self.string=\"\"
    def query(self, letter: str) -> bool:
        self.string+=letter
        #print(self.dict)
        if letter in self.dict:
            for word in self.dict[letter]:
                length=len(word)+1
                complete_word=word+letter
                if len(self.string)>=length and complete_word==self.string[- length:]:
                    return True
            return False
        else:
            return False



# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

from collections import defaultdict


class TrieNode:
    def __init__(self):
        self.children = defaultdict(TrieNode)
        self.end = False

class Trie:
    def __init__(self, words):
        self.root = TrieNode()
        for word in words:
            self.add(word[::-1])
        self.word = ''
        self.l = max(len(word) for word in words)
    
    def add(self, word):
        node = self.root
        for c in word:
            node = node.children[c]
        node.end = True
    
    def search(self, c):
        self.word = (c + self.word)[:self.l]
        node = self.root
        for c in self.word:
            if c not in node.children:
                return False
            node = node.children[c]
            if node.end:
                return True
        
        return False
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie(words)

    def query(self, letter: str) -> bool:
        return self.trie.search(letter)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.d={}
        for i in words:
            if(i[-1] not in self.d):
                self.d[i[-1]]=[i[:-1]]
            else:
                self.d[i[-1]].append(i[:-1])
                
        self.s=''
    def query(self, letter: str) -> bool:
        self.s+=letter
        if letter in self.d:
            for i in self.d[letter]:
                word=i+letter
                if len(self.s)>=len(word) and word==self.s[-len(word):]:
                    return True
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        from collections import defaultdict
        self.word = sorted(words, key = lambda x: (x[-1], len(x)))
        self.lett = \"\"
        self.d = defaultdict(str)
        for i in range(1, len(self.word) + 1):
            if not self.d[self.word[i - 1][-1]]:
                self.d[self.word[i - 1][-1]] = i   
                

    def query(self, letter: str) -> bool:
        self.lett += letter
        if not letter in self.d:
            return False
        begin = self.d[letter] - 1       
        
        for i in self.word[begin:]:
            if len(self.lett) < len(i):
                return False
            if i[-1] != letter:
                return False
            if self.lett[-len(i):] == i:
                return True
        return False
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.cache = dict()
        for word in words:
            if word[-1] not in self.cache:
                self.cache[word[-1]] = [word[:-1]]
            else:
                self.cache[word[-1]].append(word[:-1])
        
        self.string = \"\"

    def query(self, letter: str) -> bool:
        self.string += letter
        if letter in self.cache:
            for word in self.cache[letter]:
                length = len(word) + 1
                complete_word = word + letter
                if len(self.string) >= length and complete_word == self.string[- length:]:
                    return True
            return False
        else:
            return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:
    def __init__(self, words: List[str]):
        self.dic = {}
        for word in words:
            if word[-1] not in self.dic:
                self.dic[word[-1]] = [word[:-1]]
            else:
                self.dic[word[-1]].append(word[:-1])
        
        self.string = \"\"

    def query(self, letter: str) -> bool:
        self.string += letter
        if letter in self.dic:
            for word in self.dic[letter]:
                length = len(word) + 1
                complete_word = word + letter
                if len(self.string) >= length and complete_word == self.string[- length:]:
                    return True
            return False
        else:
            return False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie={}
        node=self.trie
        for i in words:
            for ch in i[::-1]:
                if ch not in node:
                    node[ch]={}
                node=node[ch]
            node['$']=True
            node=self.trie
        self.stream=''
        

    def query(self, letter: str) -> bool:
        self.stream+=letter
        node=self.trie
        def check(s,node):
            if '$' in node:
                return True
            for ch in s:
                if ch in node:
                    return check(s[1:],node[ch])
                else:
                    return False
        return check(self.stream[::-1],node)
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker(object):

# class StreamChecker:

    def __init__(self, words: List[str]):
        self.s = ''
        self.dic = collections.defaultdict(set)
        for w in words:
            self.dic[w[-1]].add(w)
                

    def query(self, letter: str) -> bool:
        self.s += letter
        return any(self.s.endswith(w) for w in self.dic[letter])

class StreamChecker:

    def __init__(self, words: List[str]):
        self.memo = {}
        self.words = set()
        words_ = [word[::-1] for word in words]
        for word in words_:
            for i in range(len(word)-1):
                self.memo[word[:i+1]]=0
        
        for word in words_:
            self.memo[word]=1
        
        self.hist = []
        
        #print(self.memo)
    
    def query(self, letter: str) -> bool:
        self.hist.insert(0,letter)
        w = ''
        for i in range(len(self.hist)):
            w+=self.hist[i]
            #print(w)
            c = self.memo.get(w,None)
            if c is None:
                return False
            if c:
                return True
            
        return False



class node:
    def __init__(self):
        self.child=[None]*26
        self.end=False
class trie:
    def __init__(self):
        self.q=node()
    def insert(self,sen):
        sen=sen[::-1]
        p=self.q
        for x in sen:
            if p.child[ord(x)-ord('a')]==None:
                p.child[ord(x)-ord('a')]=node() 
            p=p.child[ord(x)-ord('a')]
        p.end=True
class StreamChecker:
   
    def __init__(self, words: List[str]):
        self.p1=trie()
        self.s=\"\"
        for x in words:
            self.p1.insert(x)
            
    def query(self, letter: str) -> bool:
        self.s+=letter
        root=self.p1.q
        #ind=ord(letter)-ord('a')
        for x in self.s[::-1]:
            ind=ord(x)-ord('a')
            root=root.child[ind]
            if root!=None:
                if root.end==True: 
                    return True
            else:
                break

        return False 
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.stream = deque([])

        for word in set(words):
            node = self.trie       
            for ch in word[::-1]:
                if not ch in node:
                    node[ch] = {}
                node = node[ch]
            node['$'] = word
        
        
    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        
        node = self.trie
        for ch in self.stream:
            if '$' in node:
                return True
            if not ch in node:
                return False
            node = node[ch]
        return '$' in node


class StreamChecker:

    def __init__(self, words: List[str]):
        Trie = lambda: collections.defaultdict(Trie)
        self.trie = Trie()
        for word in words:
            reduce(dict.__getitem__, word[::-1] + \"$\", self.trie)
        self.queries = []

    def query(self, letter: str) -> bool:
        self.queries.append(letter)
        curr = self.trie
        #print(\"query\")
        for i in range(len(self.queries)-1, -1, -1):
            c = self.queries[i]
            if \"$\" in curr:
                return True
            if c not in curr:
                return False
            curr = curr[c]
        return \"$\" in curr


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Node:
    def __init__(self):
        self.children = {}
        self.stop = False
        
class Trie:
    def __init__(self):
        self.word = Node()
    
    def insert(self, word):
        word = word[::-1]
        curr = self.word
        for l in word:
            node = curr.children.get(l, Node())
            curr.children[l] = node
            curr = node
        curr.stop = True

    
    def search(self, word):
        curr = self.word
        
        for l in word:
            node = curr.children.get(l, None)
            
            if not node:
                return False
            elif node.stop:
                return True
            curr = node
        return curr.stop
    

class StreamChecker:

    def __init__(self, words: List[str]):
        self.t = Trie()
        for word in words:
            self.t.insert(word)
        self.pointer = ''

    def query(self, letter: str) -> bool:
        self.pointer += letter

        return self.t.search(self.pointer[::-1])
        

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import defaultdict

class StreamChecker:

    def __init__(self, words: List[str]):
        self.Queries=''
        self.Words=defaultdict(list)
        for w in words:
            self.Words[w[-1]].append(w)

    def query(self, letter: str) -> bool:
        self.Queries+=letter
        if len(self.Queries)>2000:
            self.Queries=self.Queries[1:]    
        for k in self.Words[letter]:
            i=len(k)
            if i<=len(self.Queries):
                if self.Queries[-i:]==k:
                  return True
        return False
        

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        
        self.wordSet=set(words)
        lSet=set()
        self.lastL=set()
        for word in words:
            lSet.add(len(word))
            self.lastL.add(word[-1])
        self.l=list(lSet)
        self.l.sort()
        self.q=''
        
    def query(self, letter: str) -> bool:
        self.q=self.q+letter
        
        if letter in self.lastL:
            for i in range(len(self.l)):
                if self.l[i]>len(self.q):
                    break
                elif self.q[-self.l[i]:] in self.wordSet:
                    return True
        return False
        
        

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)



class Trie:
    def __init__(self):
        self.children = [None] * 26
        self.endOfWord = False
    def insert(self, s):
        t = self
        for c in s:
            if t.children[ord(c)-ord(\"a\")] == None:
                t.children[ord(c)-ord(\"a\")] = Trie()
            t = t.children[ord(c)-ord(\"a\")]
        t.endOfWord = True
    
    def search(self, s):
        t = self
        for c in s:
            if t.children[ord(c)-ord(\"a\")] == None:
                return False
            t = t.children[ord(c)-ord(\"a\")]
            if t.endOfWord:
                return True
        return False
    
class StreamChecker:
    def __init__(self, words: List[str]):
        self.t = Trie()
        self.stream = collections.deque()
        for w in words:
            self.t.insert(reversed(w))
            
    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        return self.t.search(self.stream)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie={}
        # self.min=40000
        self.searchWord=''
        for word in words:
            word=word[::-1]
            # self.min=len(word) if len(word)<self.min else self.min
            self.insertToTrie(self.trie, word)
            
    def insertToTrie(self, trie, word):
        if word[0] not in trie:
            trie[word[0]] = {\"value\":{}, \"isLast\":len(word)==1}
        if len(word)==1:
            trie[word[0]][\"isLast\"] = True
            return
        self.insertToTrie(trie[word[0]][\"value\"], word[1:])
            
    def searchForWord(self, trie, word):
        if not word or word[0] not in trie:
            return False
        if trie[word[0]][\"isLast\"]:
            return True
        return self.searchForWord(trie[word[0]][\"value\"], word[1:])

    def query(self, letter: str) -> bool:
        # if(self.min):
        #     self.min-=1
        #     return False
        self.searchWord = letter + self.searchWord
        result = self.searchForWord(self.trie, self.searchWord)
        return result


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self):
        self.children = [None]*26
        self.isWord = False

class Trie:
    def __init__(self):
        self.root = TrieNode()
        
    def add(self,word):
        cur = self.root
        for c in word:
            if cur.children[ord(c)-ord('a')] == None:
                cur.children[ord(c)-ord('a')] = TrieNode()
            cur = cur.children[ord(c)-ord('a')]
        cur.isWord = True
        
    def search(self,word):
        
        
            
        #return self.root.children[ord(word[0]) - ord('a')]
        
        return self.__searchHelper(self.root,word,0)

    def __searchHelper(self,cur,word,word_index):
        # 提前终止: word的一部分已经匹配到了Trie
        if cur.isWord:
            return True
        
        # 重点4: 最终托底: 过了一遍word
        if len(word) == word_index:
            return cur.isWord
        
        
        
        
        char = word[word_index]
        temp = cur.children[ord(char)-ord('a')]
        
        return temp != None and self.__searchHelper(temp,word,word_index+1)
        
            
        
        

class StreamChecker:

    def __init__(self, words: List[str]):
        self.storage = Trie()
        self.prefix = ''
        # 重点1: 存的时候 倒着存
        for word in words:
            self.storage.add(word[::-1])
        
        
    def query(self, letter: str) -> bool:
        # 重点2: nonlocal stream word
        self.prefix += letter
        # 重点3: 搜的时候 倒着搜
        return self.storage.search(self.prefix[::-1])


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Node:
    def __init__(self):
        self.kids = collections.defaultdict(Node)
        self.end = False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = Node()
        self.s = \"\"
        for word in words:
            t = self.root
            for w in word[::-1]:
                t = t.kids[w]
            t.end = True

    def query(self, letter: str) -> bool:
        self.s += letter
        def dfs(t, word):
            for w in word:
                if w not in t.kids:
                    return False
                t = t.kids[w]
                if t.end:
                    return True
            return False
        return dfs(self.root, self.s[::-1])


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:
    def __init__(self, words: List[str]):
        from collections import deque
        self.stream = deque()
        self.trie = {\"_\": False}
        self.max_stream_size = 0
        for word in words:
            self.max_stream_size = max(self.max_stream_size, len(word))
            node = self.trie
            for char in word[::-1]:
                if char not in node:
                    node[char] = {\"_\": False}
                node = node[char]
            node[\"_\"] = True
        #print(self.trie)

    def query(self, letter: str) -> bool:
        self.stream.append(letter)
        if len(self.stream) > self.max_stream_size:
            self.stream.popleft()
        
        node = self.trie
        #print(node)
        #print(self.stream)
        for idx in range(len(self.stream)-1, -1, -1):
            if node[\"_\"]:
                return True
            char = self.stream[idx]
            if char not in node:
                return node[\"_\"]
            node = node[char]
        #print(self.stream)
        return node[\"_\"]


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self):
        self.children = collections.defaultdict()
        self.terminating = False
        
class Trie():
    def __init__(self):
        self.root = self.get_node()
    def get_node(self):
        return TrieNode()
    def get_index(self, ch):
        return ord(ch) - ord('a')
    def insert(self, word):
        root = self.root
        len1 = len(word)
        for i in range(len1):
            index = self.get_index(word[i])
            if index not in root.children:
                root.children[index] = self.get_node()
            root = root.children.get(index)
        root.terminating = True
    def search(self, word):
        root = self.root
        len1 = len(word)
        for i in range(len1):
            index = self.get_index(word[i])
            
            if not root: return False
            if root.terminating: return True
            root = root.children.get(index)
        return True  if root and root.terminating else False

class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.ch=\"\"
        for word in words: self.trie.insert(word[::-1])
        
    def query(self, letter: str) -> bool:
        self.ch +=letter
        if len(self.ch)>2000:
            self.ch = self.ch[1:]
        return self.trie.search(self.ch[::-1])


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.st = ''
        self.dic = collections.defaultdict(set)
        for w in words:
            self.dic[w[-1]].add(w)

    def query(self, letter: str) -> bool:
        self.st += letter
        return any(self.st.endswith(w) for w in self.dic[letter])


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.children = [None]*26
        self.isWord = False

class Trie:
    def __init__(self):
        self.root = TrieNode()
        
    def add(self,word):
        cur = self.root
        for c in word:
            if cur.children[ord(c)-ord('a')] == None:
                cur.children[ord(c)-ord('a')] = TrieNode()
            cur = cur.children[ord(c)-ord('a')]
        cur.isWord = True
        
    def search(self,word):
        
        
            
        #return self.root.children[ord(word[0]) - ord('a')]
        
        return self.__searchHelper(self.root,word,0)

    def __searchHelper(self,cur,word,word_index):
        if len(word) == word_index:
            return cur.isWord
        if cur.isWord:
            return True
        
        
        char = word[word_index]
        temp = cur.children[ord(char)-ord('a')]
        
        return temp != None and self.__searchHelper(temp,word,word_index+1)
        
            
        
        

class StreamChecker:

    def __init__(self, words: List[str]):
        self.storage = Trie()
        self.prefix = ''
        
        for word in words:
            self.storage.add(word[::-1])
        
        
    def query(self, letter: str) -> bool:
        self.prefix += letter
        return self.storage.search(self.prefix[::-1])


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
    from collections import deque
    def __init__(self, words: List[str]):
        self.max = len(max(words, key=len))
        self.words = tuple(words)
        self.letters = deque(maxlen=self.max)
        
    def query(self, letter: str) -> bool:
        self.letters.append(letter)
        l = ''.join(self.letters)
        return l.endswith(self.words)
    
    
    '''
    def __init__(self, words: List[str]):
        self.words = set(words)
        self.letters = ''
        self.fragments = {}
        for w in words:
            temp = self.fragments
            for i in range(len(w)):
                sec = w[len(w)-1-i:]
                if sec not in temp:
                    temp[sec] = {}
                temp = temp[sec]
                    
    def query(self, letter: str) -> bool:
        self.letters += letter
        chars = self.letters
        
        temp = self.fragments
        for i in range(len(chars)):
            sec = chars[len(chars) - 1 - i:]
            if sec in self.words:
                return True
            if sec not in temp:
                return False
            temp = temp[sec]
    '''
    '''
    def __init__(self, words: List[str]):
        self.words = tuple(words)
        self.letters = ''
        
    def query(self, letter: str) -> bool:
        self.letters +=letter
        return self.letters.endswith(self.words)        
    '''
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Node:
    def __init__(self):
        self.isEnd = False
        self.next = {}
    def __repr__(self):
        return str(self.next)
        

class StreamChecker:

    def __init__(self, words: List[str]):
        self.dic = {}        
        for word in words:
            self.add(self.dic, word[::-1])
        print(self.dic)
        self.validLetters = \"\"
        
    def add(self, dic, word):
        currentLetter = word[0]
        if currentLetter not in dic.keys():
            dic[currentLetter] = Node()
        if len(word) != 1:
            self.add(dic[currentLetter].next, word[1:])
        else:
            dic[currentLetter].isEnd = True
            
    def __partial_query(self, dic, word):
        currentLetter = word[0]
        if currentLetter not in dic.keys():
            return False
        else:
            if dic[currentLetter].isEnd:
                return True
            else:
                if len(word) != 1:
                    return self.__partial_query(dic[currentLetter].next, word[1:])
                else:
                    return False
            
    def partial_query(self, word):
        return self.__partial_query(self.dic, word)
        

    def query(self, letter: str) -> bool:
        self.validLetters = letter + self.validLetters
        return self.partial_query(self.validLetters)
                

        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:
    def __init__(self, words: List[str]):
        self.s = ''
        self.d = collections.defaultdict(set)
        for w in words:
            self.d[w[-1]].add(w)
                

    def query(self, letter: str) -> bool:
        self.s += letter
        return any(self.s.endswith(w) for w in self.d[letter])
        

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Node:
    def __init__(self, val=None, is_end=False):
        self.child = dict()
        self.val = val
        self.is_end = is_end
class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = Node()
        for w in words:
            tmp = self.root
            for l in w[::-1]:
                if l not in tmp.child:
                    tmp.child[l] = Node(val=l)
                tmp = tmp.child[l]
            tmp.is_end = True
        self.q = []
    def query(self, letter: str) -> bool:
        if len(self.q) >= 2000:
            self.q.pop(0)
        self.q.append(letter)
        tmp = self.root
        for i in self.q[::-1]:
            if i not in tmp.child:
                return False
            tmp = tmp.child[i]
            if tmp.is_end:
                return True
        return tmp.is_end


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
    def __init__(self, words):
        self.buffer = \"\"
        self.tree = {}
        self.null = '\\0'
        for w in words:
            self.insert(w[::-1])


    def query(self, letter):
        self.buffer = letter + self.buffer
        curr = self.tree
        for c in self.buffer:
            if c in curr:
                curr = curr[c]
                if self.null in curr:
                    return True
            else:
                break
        return False

    def insert(self, word: str) -> None:
        \"\"\"
        Inserts a word into the trie.
        \"\"\"
        tree = self.tree
        for c in word:
            if c not in tree:
                tree[c] = {}
            tree = tree[c]
        tree[self.null] = {}


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

import collections
class StreamChecker:

    def __init__(self, words: List[str]):
        self.words = collections.defaultdict(list)
        self.characters = ''
        for word in words:
            self.words[word[-1]].append(word)

    def query(self, letter: str) -> bool:
        self.characters += letter
        for word in self.words[letter]:
            length = len(word)
            if self.characters[-length:] == word:
                return True
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.words = {}
        for w in words:
            if len(w) not in list(self.words.keys()):
                self.words[len(w)] = []
            self.words[len(w)].append(w)
            
        self.buffer = '';
        self.i = 0
        self.max = (max(list(self.words.keys())))
        self.res = {}

    def query(self, letter: str) -> bool:
        self.buffer += letter;
        if len(self.buffer)>self.max:
            self.buffer = self.buffer[-self.max:]
        
        
        #print(self.buffer)
        if self.buffer in list(self.res.keys()):
            return self.res[self.buffer]
        #print(self.buffer, 'checa')
        if len(self.buffer) not in list(self.words.keys()):
            return False
        
        #print(self.buffer, 'checa2')
        for i in self.words:
            if len(self.buffer) >= i and self.buffer[-i:] in self.words[i]:
                self.res[self.buffer] = True
                return True
        
        self.res[self.buffer] = False
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.s = ''
        self.dic = collections.defaultdict(set)
        for w in words:
            self.dic[w[-1]].add(w)
                

    def query(self, letter: str) -> bool:
        self.s += letter
        return any(self.s.endswith(w) for w in self.dic[letter])
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
    def __init__(self, words: List[str]):
        self.mDict = defaultdict(list)
        for word in words:
            self.mDict[word[-1]].append(word[:-1])
        self.currStr = \"\"
    def query(self, letter: str) -> bool:
        self.currStr += letter
        if letter in self.mDict:
            for curr in self.mDict[letter]:
                length = len(curr)+1
                if len(self.currStr) >= length and  (curr+letter) == self.currStr[-length:]:
                    return True
            return False
        else:#No word so far ending in this letter
            return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TreeNode:
    def __init__(self):
        self.dict = defaultdict(TreeNode)
        self.result = False

class StreamChecker:
    def __init__(self, words: List[str]):
        self.tree = TreeNode()
        self.text = ''
        for word in words:
            curr = self.tree
            for c in word[::-1]:                
                curr = curr.dict[c]
            curr.result = True
            
    def query(self, letter: str) -> bool:
        self.text += letter
        curr = self.tree
        for c in self.text[::-1]:
            if c not in curr.dict:
                break
            curr = curr.dict[c]
            if curr.result:
                return True
        return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.dictionary = {}
        for word in words:
            last_letter = word[-1]
            if last_letter not in self.dictionary:
                self.dictionary[last_letter] = [word]            
            else:
                self.dictionary[last_letter].append(word)
        self.queries =''
            
    def query(self, letter: str) -> bool:
        self.queries += letter
        if letter not in self.dictionary:
            return False
        else:
            for word in self.dictionary[letter]:
                length = len(word)
                if self.queries[-length:] == word:
                    return True
            return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.is_word = False
        self.children = collections.defaultdict(TrieNode)
        
class StreamChecker:

    def __init__(self, words: List[str]):
        if not words: return False
        self.root = TrieNode()
        for word in words:
            self.addNode(word[::-1])
        self.buff = []
        self.maxl = len(max(words, key = lambda x: len(x)))
        

    def query(self, letter: str) -> bool:
        self.buff.append(letter)
        s = \"\"
        for i in range(len(self.buff) - 1, -1, -1):
            s += self.buff[i]
            if len(s) > self.maxl: 
                break
            print(s)
            res = self.findWord(s)
            if not res: return False
            if res.is_word: return True
        return False
            
        
    def addNode(self, word):
        p = self.root
        for w in word:
            if not p.children.get(w):
                p.children[w] = TrieNode()
            p = p.children[w]
        p.is_word = True
    
    def findWord(self,word):
        p = self.root
        for w in word:
            if not p.children.get(w):
                return False
            p = p.children[w]
            
        return p

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__ (self):
        self.kids = {}
        self.isWord = False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.q = collections.deque(maxlen = max(len(x) for x in words))
        self.root = TrieNode()
        for x in words:
            cur = self.root
            for c in x[::-1]:
                if c not in cur.kids:
                    cur.kids[c] = TrieNode()
                cur = cur.kids[c]
                if cur.isWord:
                    break
            cur.isWord = True

    def query(self, letter: str) -> bool:
        def helper(word):
            cur = self.root
            for c in word:
                if c in cur.kids:
                    cur = cur.kids[c]
                    if cur.isWord:
                        return True
                else:
                    return False
            return False
            
        self.q.appendleft(letter)
        cur = self.root
        for c in self.q:
            if c in cur.kids:
                cur = cur.kids[c]
                if cur.isWord:
                    return True
            else:
                return False
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker2:

    def __init__(self, words: List[str]):
        self.words = words
        self._m = set([])

    def query(self, letter: str) -> bool:
        exists = False
        updated_list = set([])
        for ind, word in enumerate(self.words):
            if letter == word:
                exists = True
            if letter == word[0] and len(word) > 1:
                updated_list.add((0, ind))
        for ind, wi in list(self._m):
            if letter == self.words[wi][ind+1:]:
                exists = True
            elif letter == self.words[wi][ind+1] and len(self.words[wi][ind+1:]) > 1:
                updated_list.add((ind+1, wi))
        self._m = updated_list
        return exists

class StreamChecker:

    def __init__(self, words: List[str]):
        self.dic = {}
        for word in words:
            if word[-1] not in self.dic:
                self.dic[word[-1]] = [word[:-1]]
            else:
                self.dic[word[-1]].append(word[:-1])
        
        self.string = \"\"

    def query(self, letter: str) -> bool:
        self.string += letter
        if letter in self.dic:
            for word in self.dic[letter]:
                length = len(word) + 1
                complete_word = word + letter
                if len(self.string) >= length and complete_word == self.string[- length:]:
                    return True
            return False
        else:
            return False
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.s=''
        self.di = collections.defaultdict(set)
        for w in words:
            self.di[w[-1]].add(w)

    def query(self, letter: str) -> bool:
        self.s+=letter
        return any(self.s.endswith(w) for w in self.di[letter])
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.dic = {}
        for word in words:
            if word[-1] not in self.dic:
                self.dic[word[-1]] = [word[:-1]]
            else:
                self.dic[word[-1]].append(word[:-1])
        
        self.string = \"\"

    def query(self, letter: str) -> bool:
        self.string += letter
        if letter in self.dic:
            for word in self.dic[letter]:
                length = len(word) + 1
                complete_word = word + letter
                if len(self.string) >= length and complete_word == self.string[- length:]:
                    return True
            return False
        else:
            return False

from collections import defaultdict

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

class StreamChecker:
    def __init__(self, words: List[str]):
        self.stream = ''
        self.trie = Trie()
        
        for word in words:
            curr = self.trie
            for ch in word[::-1]:
                curr = curr.children[ch]
            curr.is_word = True

    def query(self, letter: str) -> bool:
        self.stream += letter
        curr = self.trie
        
        for ch in self.stream[::-1]:
            if ch not in curr.children:
                return False
            
            curr = curr.children[ch]
            
            if curr.is_word:
                return True
        
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.dic={}
        for word in words:
            if word[-1] not in self.dic:
                self.dic[word[-1]] = [word[:-1]]
            else:
                self.dic[word[-1]].append(word[:-1])
        
        self.string = \"\"

    def query(self, letter: str) -> bool:
        self.string += letter
        if letter in self.dic:
            for word in self.dic[letter]:
                length = len(word) + 1
                complete_word = word + letter
                if len(self.string) >= length and complete_word == self.string[- length:]:
                    return True
            return False
        else:
            return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode():
    def __init__(self):
        self.child = collections.defaultdict(TrieNode)
        self.isWord = False
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = TrieNode()
        self.res = []
        for word in words:
            self.add(word)
        

    def query(self, letter: str) -> bool:
        curr = self.root
        self.res.insert(0,letter)
        for char in self.res:
            if curr.isWord:
                return True
            if not curr.child.get(char):
                return False
            curr = curr.child[char]
        return curr.isWord
    
    def add(self,word):
        curr = self.root
        for char in word[::-1]:
            curr = curr.child[char]
        curr.isWord = True


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import deque

class Trie:
    def __init__(self):
        self.last_nodes = {}

    def add(self, word):
        last_char = word[-1]
        word_len = len(word)
        if last_char in self.last_nodes:
            if word_len in self.last_nodes[last_char]:
                self.last_nodes[last_char][word_len].add(word)
            else:
                self.last_nodes[last_char][word_len] = set([word])
        else:
            self.last_nodes[last_char] = {word_len: set([word])}
    
    def smart_search(self, word):
        last_char = word[-1]
        if last_char in self.last_nodes:
            for word_len in range(1, len(word) + 1):
                if word_len in self.last_nodes[last_char] and\\
                        word[-word_len:] in self.last_nodes[last_char][word_len]:
                    return True
        return False
                    

class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.max_size = 0
        self.cache = deque()
        
        for word in words:
            self.trie.add(word)
            self.max_size = max(len(word), self.max_size)

    def query(self, letter: str) -> bool:
        self.cache.append(letter)
        if len(self.cache) > self.max_size:
            self.cache.popleft()

        return self.trie.smart_search(''.join(self.cache))
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Trie:
  def __init__(self, words):
    self.trie = {}
    for word in words:
      self.add(word)
  
  def add(self, word):
    def add_helper(prev, i):
      if i == len(word) - 1:
        prev[word[i]] = {None: None}
        return
      
      char = word[i]
      if char not in prev:
        prev[char] = {}
      add_helper(prev[char], i + 1)
    add_helper(self.trie, 0)
    
  def contains(self, word):
    def dfs(prev, i):
      if i == len(word):
        return False
      if word[i] in prev and None in prev[word[i]]:
        return True
      
      return dfs(prev[word[i]], i + 1) if word[i] in prev else False
    return dfs(self.trie, 0)
      

class StreamChecker:

  def __init__(self, words: List[str]):
    self.trie = Trie([''.join(reversed(w))for w in words])
    self.word = ''

  def query(self, letter: str) -> bool:
    self.word = ''.join([letter, self.word])
    return self.trie.contains(self.word)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import deque, defaultdict


class StreamChecker:

    def __init__(self, words: List[str]):
        words = sorted(words, key=len)
        self.words_by_len = defaultdict(set)
        for word in words:
            if all(word[-length:] not in words_set for length, words_set in list(self.words_by_len.items())):
                self.words_by_len[len(word)].add(word)
        
        self.search_history = deque(maxlen=max(self.words_by_len.keys()))

    def query(self, letter: str) -> bool:
        self.search_history.append(letter)
        history = ''.join(self.search_history)
        
        return any(history[-length:] in words_set for length, words_set in list(self.words_by_len.items()))
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.dic = {}
        for word in words:
            if word[-1] not in self.dic:
                self.dic[word[-1]] = [word[:-1]]
            else:
                self.dic[word[-1]].append(word[:-1])
        
        self.string = \"\"

    def query(self, letter: str) -> bool:
        self.string += letter
        if letter in self.dic:
            for word in self.dic[letter]:
                length = len(word) + 1
                complete_word = word + letter
                if len(self.string) >= length and complete_word == self.string[- length:]:
                    return True
            return False
        else:
            return False
            
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self):
        self.endOfWord=False
        self.children={}
class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie=TrieNode()
        self.stream=collections.deque()
        for word in words:
            node=self.trie
            for c in word[::-1]:
                if not c in node.children:
                    childNode=TrieNode()
                    node.children[c]=childNode
                node=node.children[c]
            node.endOfWord=True
       
    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        node=self.trie
        for c in self.stream: # we treat the stream like a stack, as we start reading it from the last insertion point.
            if not c in node.children:
                return False
            node=node.children[c]
            if node.endOfWord:
                return True
        return False


    #solution 2 a bit different trie implementation
'''
class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie={}
        self.stream=collections.deque()
        for word in words:
            node=self.trie
            for ch in word[::-1]:
                if not ch in node:
                    node[ch]={}
                node=node[ch]
            node['$']=word
        
    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        node=self.trie
        for c in self.stream:
            if '$' in node:
                return True
            if not c in  node:
                return False
            node=node[c]
        #print('$' in node)
        return '$' in node
'''

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)



class StreamChecker:

    def __init__(self, words: List[str]):
        self.words = set(words)
        self.max_len = max((len(x) for x in self.words), default=0)
        self.q = ''
        self.num_end = min(1, self.max_len)
        self.ends = {}
        for i in range(1, self.num_end + 1):
            self.ends[i] = set(x[-i:] for x in self.words if len(x) >= i)
        # print(self.ends)
        

    def query(self, letter: str) -> bool:
        self.q += letter
        if len(self.q) > self.max_len:
            self.q = self.q[1:]
        for i in range(1, self.num_end + 1):
            # print(i, self.q[-i:])
            if self.q[-i:] not in self.ends[i]:
                return False
        # print('cont', i, self.q)
        for i in range(0, self.max_len):
            # print(~i, self.q[~i:])
            if self.q[~i:] in self.words:
                # print(self.q[~i:])
                return True
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    def __init__(self):
        self.wordEndsHere = False
        self.children = dict()
        
    def addWord(self, word):
        if not word:
            self.wordEndsHere = True
        else:
            if word[0] not in self.children:
                self.children[word[0]] = Trie()
            self.children[word[0]].addWord(word[1:])
    
    def findWord(self, word):
        if self.wordEndsHere:
            return True
        
        if not word:
            return self.wordEndsHere
        elif word[0] not in self.children:
            return False
        else:
            return self.children[word[0]].findWord(word[1:])

class StreamChecker:
    def __init__(self, words: List[str]):
        self.maxLength = 0
        self.letters = []
        self.trie = Trie()
        
        for w in words:
            self.trie.addWord(w[::-1])
            self.maxLength = max(self.maxLength, len(w))

    def query(self, letter: str) -> bool:
        self.letters.append(letter)
        sliceLength = min(len(self.letters), self.maxLength)
        target = ''.join(self.letters[(len(self.letters) - sliceLength):])[::-1]
        return self.trie.findWord(target)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.memo = {}
        self.words = set()
        words_ = [word[::-1] for word in words]
        for word in words_:
            for i in range(len(word)-1):
                self.memo[word[:i+1]]=0
        
        for word in words_:
            self.memo[word]=1
        
        self.hist = []
        
        #print(self.memo)
    
    def query(self, letter: str) -> bool:
        self.hist.insert(0,letter)
        for i in range(len(self.hist)):
            #print(w)
            c = self.memo.get(''.join(self.hist[:i+1]),None)
            if c is None:
                return False
            if c:
                return True
            
        return False



# from functools import reduce
from collections import deque, defaultdict


class StreamChecker:

    def __init__(self, words: List[str]):
        self.words = words
        self.stream = ''
        self.letters, self.end_letter = self.prep()

    def prep(self):
        letters = set()
        end_letter = defaultdict(list)
        # self.words.sort(key=lambda x: len(x))
        for i, word in enumerate(self.words):
            letters = letters.union(set(word))
            end_letter[word[-1]].append(i)
        return letters, end_letter

    def query(self, letter: str) -> bool:
        self.stream += letter
        if letter not in self.letters:
            return False
        for i in self.end_letter.get(letter, []):
            # if len(self.stream) < len(self.words[i]):
            #     return False
            if self.stream[-len(self.words[i]):] == self.words[i]:
                return True
        return False


#5:58
class TrieNode:
    def __init__(self):
        self.val = 0
        self.children = [None]*26
        
class Trie:
    def __init__(self):
        self.root = TrieNode()
        
    def addWord(self, word):
        curr = self.root
        for char in word:
            if curr.children[ord(char) - ord('a')] is None:
                curr.children[ord(char) - ord('a')] = TrieNode()
            curr = curr.children[ord(char) - ord('a')]
        curr.val = 1
        
    def searchWord(self, word):
        curr = self.root
        for char in word:
            if curr.children[ord(char) - ord('a')] is None:
                return False
            curr = curr.children[ord(char) - ord('a')]
            if curr.val == 1:
                return True
        return False
        

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        max_len = 0
        for word in words:
            max_len = max(max_len, len(word))
            self.trie.addWord(\"\".join([x for x in reversed(word)]))
        self.query_text = \"\"
        self.max_len = max_len

    def query(self, letter: str) -> bool:
        self.query_text += letter
        if len(self.query_text) >self.max_len:
            self.query_text = self.query_text[1:]
        reversed_query = \"\".join([x for x in reversed(self.query_text)])
        return self.trie.searchWord(reversed_query)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.s = ''
        self.l = max([len(w) for w in words])
        self.dic = collections.defaultdict(set)
        for w in words:
            self.dic[w[-1]].add(w)
                

    def query(self, letter: str) -> bool:
        self.s += letter
        return any(self.s[-1*self.l:].endswith(w) for w in self.dic[letter])

class StreamChecker:

    def __init__(self, words: List[str]):
        self.words = words
        self.chars = \"\"
        self._last_letters = set(w[-1] for w in words)
        
    def query(self, letter: str) -> bool:
        self.chars += letter
        if letter not in self._last_letters:
            return False
        return any(self.chars.endswith(w) for w in self.words)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.tries = [False, [[] for _ in range(26)]]
        for word in words:
            self.build(word[::-1])
        self.stream = ''
            
    def build(self, word):
        temp_level = self.tries
        for c in word:
            if len(temp_level[1][ord(c) - ord('a')]) == 0:
                temp_level[1][ord(c) - ord('a')] = [False, [[] for _ in range(26)]]
            temp_level = temp_level[1][ord(c) - ord('a')]
            
        temp_level[0] = True
       
        

    def query(self, letter: str) -> bool:
        self.stream += letter
        temp_level = self.tries
        for c in self.stream[::-1]:
            if len(temp_level[1][ord(c) - ord('a')]) == 0:
                return False
            temp_level = temp_level[1][ord(c) - ord('a')]
            if temp_level[0]:
                return True
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Node:
    def __init__(self, val):
        self.val = val
        self.children = [None] * 26
        self.isWord = False


class Trie:
    def __init__(self, words):
        self.root = Node('')

        for word in words:
            p = self.root
            for ind in range(len(word) - 1, -1, -1):
                ch = word[ind]
                if p.children[ord(ch) - ord('a')] is None:
                    new_node = Node(ch)
                    p.children[ord(ch) - ord('a')] = new_node
                p = p.children[ord(ch) - ord('a')]
                if ind == 0:
                    p.isWord = True


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie(words)
        self.pointer_queue = []
        self.stream = []

    def query(self, letter: str) -> bool:
        self.stream.insert(0, letter)
        
        p = self.trie.root
        for ch in self.stream:
            if p.children[ord(ch) - ord('a')]:
                p = p.children[ord(ch) - ord('a')]
            else:
                return False
            if p.isWord:
                return True
        return False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie={}
        self.q = ''
        for i in words:
            if i[-1] not in self.trie:
                self.trie[i[-1]]=[i[:-1]]
            else:
                self.trie[i[-1]].append(i[:-1])        

    def query(self, letter: str) -> bool:

        trie= self.trie
        self.q += letter
        if letter not in trie: return False
        
        for i in trie[letter]:
            l=len(i)
            if self.q[-l-1:-1]==i:
                return True
        
        return False





class Trie:
    def __init__(self):
        self.wordEndsHere = False
        self.children = dict()
        
    def addWord(self, word):
        if not word:
            self.wordEndsHere = True
        else:
            if word[0] not in self.children:
                self.children[word[0]] = Trie()
            self.children[word[0]].addWord(word[1:])
    
    def findWord(self, word):
        if self.wordEndsHere:
            return True
        
        if not word:
            return self.wordEndsHere
        elif word[0] not in self.children:
            return False
        else:
            return self.children[word[0]].findWord(word[1:])

class StreamChecker:
    def __init__(self, words: List[str]):
        self.maxLength = 0
        self.letters = []
        self.trie = Trie()
        
        for w in words:
            self.trie.addWord(w[::-1])
            self.maxLength = max(self.maxLength, len(w))

    def query(self, letter: str) -> bool:
        self.letters.append(letter)
        
        sliceLength = min(len(self.letters), self.maxLength)
        
        target = ''.join(self.letters[(len(self.letters) - sliceLength):])[::-1]
        return self.trie.findWord(target)

class Node:
    def __init__(self, val):
        self.val = val
        self.children = {}
        self.isWord = False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = Node(\"thisisroot\")
        
        for word in words:
            node = self.root
            for char in word[::-1]:
                if not char in node.children:
                    node.children[char] = Node(char)
                node = node.children[char]
            node.isWord = True
            
        self.prefix = \"\"
            
    def query(self, letter: str) -> bool:
        self.prefix += letter
        node = self.root
        for char in self.prefix[::-1]:
            if char not in node.children: break
            tmp = node.children[char]
            if tmp.isWord: return True
            node = tmp
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

from collections import defaultdict

class StreamChecker:

    def __init__(self, words: List[str]):
        self.Queries=''
        self.Words=defaultdict(list)
        for w in words:
            self.Words[w[-1]].append(w)

    def query(self, letter: str) -> bool:
        self.Queries+=letter
        if len(self.Queries)>2000:
            self.Queries=self.Queries[1:]    
        for k in self.Words[letter]:
            i=len(k)
            if i<=len(self.Queries):
                if self.Queries[-i:]==k:
                  return True
        return False

class StreamChecker:
    
    # I just used a trie, and inserted into it the reversals of the words. So by looking up something in the trie, I can tell if those letters are at the end of a word in the trie. But the leetcode results tell me my result is not that efficient, so I should check the Discuss tab to see better results. Maybe I am wasting time first doing the \"startsWith\" lookup, and if that is successful, having to begin again with the \"search\" lookup. There should be a way to have a startswith method that also tells you if it is or is not a word.

    def __init__(self, words: List[str]):
        
        class Trie:
    
            class TreeNode:
        
                def __init__(self):
                    self.children = [None] * 26
                    self.isEndOfWord = False
    
            def __init__(self):
                \"\"\"
                Initialize your data structure here.
                \"\"\"
                self.root = self.TreeNode()
        

            def insert(self, word: str) -> None:
                \"\"\"
                Inserts a word into the trie.
                \"\"\"
                node = self.root
                for i in range(len(word)):
                    letter = word[i]
                    index = ord(letter) - ord('a')
                    if node.children[index] == None:
                        node.children[index] = self.TreeNode() 
                    if i == len(word) - 1:
                        node.children[index].isEndOfWord = True
                    node = node.children[index]
                
        
            def search(self, word: str) -> bool:
                \"\"\"
                Returns if the word is in the trie.
                \"\"\"
                node = self.root
                for i in range(len(word)):
                    letter = word[i]
                    index = ord(letter) - ord('a')
                    if node.children[index] == None:
                        return
                    else:
                        if i == len(word) - 1:
                            return node.children[index].isEndOfWord
                        node = node.children[index]
        

            def startsWith(self, prefix: str) -> bool:
                \"\"\"
                Returns if there is any word in the trie that starts with the given prefix.
                \"\"\"
                node = self.root
                for i in range(len(prefix)):
                    letter = prefix[i]
                    index = ord(letter) - ord('a')
                    if node.children[index] == None:
                        # return False
                        return (False, False)
                    else:
                        if i == len(prefix) - 1:
                            #return True
                            if node.children[index].isEndOfWord:
                                return (True, True)
                            else:
                                return (True, False)
                        node = node.children[index]
        
        self.trie = Trie()
        for word in words:
            rev = word[::-1]
            self.trie.insert(rev)
        self.letters = []

    def query(self, letter: str) -> bool:
        self.letters.append(letter)
        i = len(self.letters) -1
        res = \"\"
        while i >= 0:
            res += self.letters[i]
            starts, isWord = self.trie.startsWith(res)
            if not starts:
                return False
            if isWord:
                return True
            #if not self.trie.startsWith(res):
            #    return False
            #else:
            #    if self.trie.search(res):
            #        return True
            i -= 1


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.words=set(words)
        self.maxx = len(max(self.words,key=len))
        self.tails = {word[-1] for word in words}
        self.qs = ''
    

    def query(self, letter: str) -> bool:
        self.qs +=letter
        if len(self.qs)>self.maxx:
            self.qs = self.qs[1:]
        if letter not in self.tails:
            return False
        N = len(self.qs)
        return any((self.qs[i:N] in self.words for i in range(N-1,-1,-1)))
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    

    def __init__(self, words):
        self.words = []
        self.store = {}
        self.stack = ''
        self.sample = 1
        for w in words:
            if not w:
                continue
            self.insertStore(w[::-1], self.store)

    def query(self, letter):
        self.stack += letter
        return self.queryStore(self.stack, self.store)

    def insertStore(self, w, store):
        if w[:self.sample] not in store:
            store[w[:self.sample]] = {}
        if len(w) <= self.sample:
            store[w[:self.sample]]['!'] = None
        else:
            self.insertStore(w[self.sample:], store[w[:self.sample]])

    def queryStore(self, stack, store):
        if not stack:
            return False
        s = stack[:-self.sample-1:-1]
        if s in store:
            if '!' in store[s]:
                return True
            if self.queryStore(stack[:-self.sample], store[s]):
                return True
        for i in range(1, self.sample):
            if s[:i] in store:
                return True
        return False





class TrieNode:
    def __init__(self):
        self.endOfWord=False
        self.children={}
class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie=TrieNode()
        self.stream=collections.deque()
        for word in words:
            node=self.trie
            for c in word[::-1]:
                if not c in node.children:
                    childNode=TrieNode()
                    node.children[c]=childNode
                node=node.children[c]
            node.endOfWord=True
       
    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        node=self.trie
        for c in self.stream:
            if not c in node.children:
                return False
            node=node.children[c]
            if node.endOfWord:
                return True
        return node.endOfWord

'''
class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie={}
        self.stream=collections.deque()
        for word in words:
            node=self.trie
            for ch in word[::-1]:
                if not ch in node:
                    node[ch]={}
                node=node[ch]
            node['$']=word
        
    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        node=self.trie
        for c in self.stream:
            if '$' in node:
                return True
            if not c in  node:
                return False
            node=node[c]
        #print('$' in node)
        return '$' in node
'''

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)



class StreamChecker:

    def __initv1__(self, words: List[str]):
        self.dictionary:Dict[int, List[str]] = {}
        for w in words:
            l:int = len(w)
            if l not in self.dictionary:
                self.dictionary[l] = []
            self.dictionary[l].append(w)
            
        self.l:List[int] = sorted(self.dictionary.keys())
            
        print(self.l)
            
        
            
    def __init__(self, words: List[str]):
        self.dictionary:Dict[str, List[str]] = {}
        
        for w in words:
            if w[-1] in self.dictionary.keys():
                self.dictionary[w[-1]].append(w)
            else:
                self.dictionary[w[-1]] = [w]
                
        print(self.dictionary)
                
        self.word:str = \"\"

    def query(self, letter: str) -> bool:
        self.word += letter
        
        if letter in self.dictionary:
            for w in self.dictionary[letter]:
                l:int = len(w)
                if len(self.word) >= l and w == self.word[-l:]:
                    return True
            
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Trie:
    
    def __init__(self):
        self.children = {}
        self.isWord = False
    
    def add(self, word: str):
        cur = self
        for char in word:
            if char not in cur.children:
                cur.children[char] = Trie()
            cur = cur.children[char]
        cur.isWord = True
    
    def contains(self, prefix: str):
        cur = self
        for char in prefix:
            if char not in cur.children:
                return False
            cur = cur.children[char]
            if cur.isWord:
                return True
        return False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.prefix = \"\"
        self.trie = Trie()
        for word in words:
            self.trie.add(word[::-1])

    def query(self, letter: str) -> bool:
        self.prefix += letter
        return self.trie.contains(self.prefix[::-1])
    
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

from collections import defaultdict
class StreamChecker:

    def __init__(self, words: List[str]):
        
        self.words=words
        self.rev_words={}
        self.n=0
        self.cur_word=''
        self.dic=defaultdict(list)
        
        for i,word in enumerate(words):
            rev_word=word[::-1]
            self.rev_words[i]=rev_word
            self.dic[rev_word[0]].append(i)
            
            if len(word)>self.n:
                self.n=len(word)        
        
        #print(self.rev_words)
        #print(self.dic)
    
    def query(self, letter: str) -> bool:
        
        if len(self.cur_word)==self.n:
            self.cur_word=self.cur_word[1:]
        
        self.cur_word+=letter
        
        #print(self.cur_word)
        
        if letter in self.dic:
            index=self.dic[letter]
            
            for i in index:
                word=self.rev_words[i]
                
                if len(word)<=len(self.cur_word):
                    if self.cur_word[::-1][:len(word)]==word:
                        #print(self.cur_word,word)
                        return True
            
        return False
                        

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.child={}
        self.isLeaf=False

class Trie():
    def __init__(self):
        self.root=TrieNode()
    
    def add(self,s):
        curr=self.root
        for ch in s:
            if ch not in curr.child:
                curr.child[ch]=TrieNode()
            curr=curr.child[ch]
        curr.isLeaf=True
        
    def print(self):
        curr=self.root
        
        def get(node,s):
            if node.isLeaf:
                print(\"got:\",s)
            for ch in node.child:
                get(node.child[ch],s+ch)
        get(curr,\"\")

class StreamChecker:

    def __init__(self, words: List[str]):
        self.t=Trie()
        self.q_word=''
        for word in words:
            self.t.add(word[::-1])
        #self.t.print()

    def query(self, letter: str) -> bool:
        self.q_word+=letter
        
        def find(node,s):
            for ch in s:
                if node.isLeaf:
                    return True
                if ch not in node.child:
                    return False
                node=node.child[ch]
            return node.isLeaf
            
        return find(self.t.root,self.q_word[::-1])


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.dict={}
        self.longest =0
        for word in words:
            if self.longest<len(word):
                self.longest = len(word)
            for i in range(len(word)-1,0,-1):
                if self.dict.get(len(word[i:]))==None:
                    self.dict[len(word[i:])]= {word[i:]:0}
                elif self.dict[len(word[i:])].get(word[i:])==None:
                    self.dict[len(word[i:])][word[i:]]=0
            if self.dict.get(len(word))==None:
                self.dict[len(word)]={word:1}
            else:
                self.dict[len(word)][word]=1
        self.letters=''
        
    def query(self, letter: str) -> bool:
        if len(self.letters)==self.longest:
            self.letters = self.letters[1:]
        self.letters+=letter
        i=len(self.letters)-1
        while i>=0 and self.dict[len(self.letters[i:])].get(self.letters[i:])!=None:
            if self.dict[len(self.letters[i:])][self.letters[i:]]==1:
                return True
            i-=1
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie([word[::-1] for word in words])
        self.stream = []

    def query(self, letter: str) -> bool:
        self.stream.insert(0, letter)
        curr = self.trie.head
        i = 0
        while curr and i < len(self.stream):
            curr = curr.get_element(self.stream[i])
            if not curr:
                return False
            if curr.is_word:
                return True
            i += 1


class TrieNode:
    ORDA = ord('a')

    def __init__(self, is_word: bool = False):
        self.is_word = is_word
        self.children = [None] * 26

    def get_element(self, c: str):
        idx = ord(c) - TrieNode.ORDA
        return self.children[idx]

    def ensure_element(self, c: str):
        idx = ord(c) - TrieNode.ORDA
        if not self.children[idx]:
            self.children[idx] = TrieNode()
        return self.children[idx]


class Trie:
    def __init__(self, words: List[str]):
        self.head = TrieNode()
        for word in words:
            self.add_word(word)

    def add_word(self, word: str):
        curr = self.head
        for c in word:
            curr = curr.ensure_element(c)
        curr.is_word = True


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.children = [0]*26
        self.we = 0
        self.c = 0

class Trie:

    def __init__(self):
        \"\"\"
        Initialize your data structure here.
        \"\"\"
        self.root = TrieNode()
        
    def findIndex(self, char):
        return ord(char) - ord(\"a\")
        

    def insert(self, word: str) -> None:
        \"\"\"
        Inserts a word into the trie.
        \"\"\"
        root = self.root
        for letter in word:
            index = self.findIndex(letter)
            if not root.children[index]:
                root.children[index] = TrieNode()
            root.c += 1
            root = root.children[index]
        root.we += 1
        
        

    def search(self, word: str) -> bool:
        \"\"\"
        Returns if the word is in the trie.
        \"\"\"
        root = self.root
        for letter in word:
            index = self.findIndex(letter)
            if not root.children[index]:
                return False
            root = root.children[index]
        if root.we:
            return True
        

    def startsWith(self, prefix: str) -> bool:
        \"\"\"
        Returns if there is any word in the trie that starts with the given prefix.
        \"\"\"
        root = self.root
        for letter in prefix:
            index = self.findIndex(letter)
            if not root.children[index]:
                return False
            root = root.children[index]
        return True
        
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.words = words
        self.trie = Trie()
        self.stream = \"\"
        for word in words:
            
            self.trie.insert(word[::-1])
        

    def query(self, letter: str) -> bool:
        self.stream = self.stream + letter
        l = len(self.stream)
        for i in range(l-1, -1, -1):
            a = self.stream[i:]
            # print(self.stream[i:], self.startsWith(self.stream[i:]))
            if not self.trie.startsWith(a[::-1]):
                return False
            else:
           
                if self.trie.search(a[::-1]):
                    return True
        return False
            
        
    
    
   
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = {}
        self.end = '#'    
        self.chars = ''
        
        for word in words:
            word = word[::-1]
            cnode = self.root
            word += self.end

            for c in word:
                if c in cnode:
                    cnode = cnode[c]
                else:
                    cnode[c] = {}
                    cnode = cnode[c]
        #print(self.root)
    
    def query(self, letter: str) -> bool:
        self.chars += letter
        cnode = self.root
        
        for c in self.chars[::-1]:
            #if self.chars[::-1] == 'bbbaa':
            #   print(c,cnode)

            
            if c in cnode:
                cnode = cnode[c]                
            else:
                return False
            
            if '#' in cnode:
            #    print(cnode)
                return True
        

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode: 
      
    def __init__(self): 
        self.children = [None]*26
        self.isEndOfWord = False
        
class Trie: 
      
    # Trie data structure class 
    def __init__(self): 
        self.root = self.getNode() 
  
    def getNode(self): 
        return TrieNode() 
  
    def _charToIndex(self,ch): 
        return ord(ch)-ord('a')
    
    
    def insert(self,key): 
        pCrawl = self.root 
        length = len(key) 
        for level in range(length): 
            index = self._charToIndex(key[level]) 
            if not pCrawl.children[index]: 
                pCrawl.children[index] = self.getNode() 
            pCrawl = pCrawl.children[index] 
  
        pCrawl.isEndOfWord = True
    
    def search(self, key): 
        pCrawl = self.root 
        length = len(key) 
        for level in range(length): 
            index = self._charToIndex(key[level]) 
            if not pCrawl.children[index]: 
                return 0
            pCrawl = pCrawl.children[index]
        if pCrawl != None and pCrawl.isEndOfWord:
            return 1
        if pCrawl != None:
            return 2
        return 0
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = Trie()
        # self.firsts = set()
        # self.lasts = set()
        # self.tots = set()
        for word in words:
            self.root.insert(word[::-1])
            # self.tots.add(word)
            # self.firsts.add(word[0])
            # self.lasts.add(word[-1])
        self.streams = []
        self.l = 0

    def query(self, letter: str) -> bool:
        self.streams.append(letter)
        self.l+=1
        # if letter not in self.lasts:
        #     return False
        for i in range(self.l,-1,-1):
            word = list(reversed(self.streams[i:self.l]))
            # print (word)
            if word == []:
                continue
            k = self.root.search(word)
            if k == 1:
                return True
            if k == 0:
                break

        return False
                
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.dic = {};
        for word in words:
            if word[-1] not in self.dic:
                self.dic[word[-1]] = [word[:-1]];
            else:
                self.dic[word[-1]].append(word[:-1]);
            self.s = \"\";
                                     
    def query(self, letter: str) -> bool:
        self.s += letter;
        if letter in self.dic:
            for word in self.dic[letter]:
                length = len(word) + 1;
                cw = word + letter;
                if len(self.s) >= length and cw == self.s[-length:]:
                    return True;
            return False;
        else:
            return False;


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.d = {}
        for word in words:
            if not word[-1] in self.d:
                self.d[word[-1]] = [word[:-1]]
            else:
                self.d[word[-1]].append(word[:-1])
        
        self.string = \"\"

    def query(self, letter: str) -> bool:
        self.string += letter
        if letter in self.d:
            for word in self.d[letter]:
                length = len(word) + 1
                complete_word = word + letter
                if len(self.string) >= length and complete_word == self.string[-length:]:
                    return True
            return False
        else:
            return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:
    
    # I just used a trie, and inserted into it the reversals of the words. So by looking up something in the trie, I can tell if those letters are at the end of a word in the trie. But the leetcode results tell me my result is not that efficient, so I should check the Discuss tab to see better results. Maybe I am wasting time first doing the \"startsWith\" lookup, and if that is successful, having to begin again with the \"search\" lookup. There should be a way to have a startswith method that also tells you if it is or is not a word.
    # Following up on above comment, the code below corrects that \"problem\", but it still runs in the bottom 20% of python submissions. So I should read the Discuss tab!

    def __init__(self, words: List[str]):
        
        class Trie:
    
            class TreeNode:
        
                def __init__(self):
                    self.children = [None] * 26
                    self.isEndOfWord = False
    
            def __init__(self):
                \"\"\"
                Initialize your data structure here.
                \"\"\"
                self.root = self.TreeNode()
        

            def insert(self, word: str) -> None:
                \"\"\"
                Inserts a word into the trie.
                \"\"\"
                node = self.root
                for i in range(len(word)):
                    letter = word[i]
                    index = ord(letter) - ord('a')
                    if node.children[index] == None:
                        node.children[index] = self.TreeNode() 
                    if i == len(word) - 1:
                        node.children[index].isEndOfWord = True
                    node = node.children[index]
                
        
            def search(self, word: str) -> bool:
                \"\"\"
                Returns if the word is in the trie.
                \"\"\"
                node = self.root
                for i in range(len(word)):
                    letter = word[i]
                    index = ord(letter) - ord('a')
                    if node.children[index] == None:
                        return
                    else:
                        if i == len(word) - 1:
                            return node.children[index].isEndOfWord
                        node = node.children[index]
        

            def startsWith(self, prefix: str) -> bool:
                \"\"\"
                Returns if there is any word in the trie that starts with the given prefix.
                \"\"\"
                node = self.root
                for i in range(len(prefix)):
                    letter = prefix[i]
                    index = ord(letter) - ord('a')
                    if node.children[index] == None:
                        # return False
                        return (False, False)
                    else:
                        if i == len(prefix) - 1:
                            #return True
                            if node.children[index].isEndOfWord:
                                return (True, True)
                            else:
                                return (True, False)
                        node = node.children[index]
        
        self.trie = Trie()
        for word in words:
            rev = word[::-1]
            self.trie.insert(rev)
        self.letters = []

    def query(self, letter: str) -> bool:
        self.letters.append(letter)
        i = len(self.letters) -1
        res = \"\"
        while i >= 0:
            res += self.letters[i]
            starts, isWord = self.trie.startsWith(res)
            if not starts:
                return False
            if isWord:
                return True
            #if not self.trie.startsWith(res):
            #    return False
            #else:
            #    if self.trie.search(res):
            #        return True
            i -= 1


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.tire = {}
        self.tire_reverse = {}
        self.max_size = 0
        for w in words:
            self._insert(w)
            self._insert_reverse(w[::-1])
            self.max_size = max(self.max_size, len(w))
        
        self.q = collections.deque([], self.max_size)
        self.curr = self.tire
        
    
    def _insert(self, word):
        curr = self.tire
        for c in word:
            if c not in curr:
                curr[c] = {}
            curr = curr[c]
        curr['$'] = True

    def _insert_reverse(self, word):
        curr = self.tire_reverse
        for c in word:
            if c not in curr:
                curr[c] = {}
            curr = curr[c]
        curr['$'] = True
        
    def _search(self, w):
        curr = self.tire_reverse
        for c in w:
            if c in curr:
                curr = curr[c]
                if '$' in curr:
                    return True
            else:
                return False
        
        return False

    def query(self, letter: str) -> bool:
        self.q.append(letter)
        
        if letter in self.curr:
            self.curr = self.curr[letter]
            if '$' in self.curr:
                return True
            else:
                self.curr = self.tire
            
        w = [c for c in self.q]
        return self._search(w[::-1])




# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


import itertools
class TrieNode:
    def __init__(self):
        self.end = False
        self.nodes = {}
    def insert(self, word):
        if len(word) == 0:
            self.end = True
            return
        if word[0] not in self.nodes:
            self.nodes[word[0]] = TrieNode()
        self.nodes[word[0]].insert(word[1:])
    def startsWith(self, word):
        if len(word) == 0:
            return True
        if word[0] not in self.nodes:
            return False
        return self.nodes[word[0]].startsWith(word[1:])
    def exists(self, word):
        if self.end and len(word) == 0:
            return True
        if len(word) == 0 or word[0] not in self.nodes:
            return False
        return self.nodes[word[0]].exists(word[1:])
            
#from collections import deque        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = TrieNode()
        self.longest = 0
        for word in words:
            self.longest = max(self.longest, len(word))
            self.root.insert(word[::-1])
        self.word = ''
        
    def query(self, letter: str) -> bool:
        self.word = (self.word + letter)[-self.longest:]
        for i in range(len(self.word)-1, -1,-1):
            other = self.word[i:][::-1]
            if not self.root.startsWith(other):
                break
            if self.root.exists(other):
                return True
        return False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.dict = {}
        for word in words:
            if word[-1] not in self.dict:
                self.dict[word[-1]] = [word[:-1]]
            else:
                self.dict[word[-1]].append(word[:-1])
        
        self.s = \"\"
        
    def query(self, letter: str) -> bool:
        self.s += letter
        if letter in self.dict:
            for word in self.dict[letter]:
                length = len(word) + 1
                cword = word + letter
                if len(self.s) >= length and cword == self.s[-length:]:
                    return 1
            return 0
        else:
            return 0
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.max_len = 0
        self.dequeue = collections.deque()
        self.suffix_dict = dict()

        for w in set(words):
            self.max_len = max(self.max_len, len(w))
            for i in reversed(range(len(w))):
                suffix = \"\".join(reversed(w[i:]))
                if suffix not in self.suffix_dict:
                    self.suffix_dict[suffix] = False
                if i == 0:
                    self.suffix_dict[suffix] = True

    def query(self, letter: str) -> bool:
        if len(self.dequeue) >= self.max_len:
            self.dequeue.popleft()
        self.dequeue.append(letter)

        reversed_word = ''
        for i in reversed(range(len(self.dequeue))):
            c = self.dequeue[i]
            reversed_word = reversed_word + c

            if reversed_word in self.suffix_dict:
                if self.suffix_dict[reversed_word]:
                    return True
            else:
                return False

        return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    
    def __init__(self):
        self.children = {}
        self.is_end = False

class Trie:
    
    def __init__(self):
        self.root = TrieNode()
    
    def add(self, word):
        curr = self.root
        for ch in word:
            if ch not in curr.children:
                new_node = TrieNode()
                curr.children[ch] = new_node
            curr = curr.children[ch]
        curr.is_end = True

class StreamChecker:

    def __init__(self, words: List[str]):
        self.stream = collections.deque()
        self.trie = Trie()
        for ch in words:
            self.trie.add(reversed(ch))
        

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        curr = self.trie.root
        for ch in self.stream:
            if ch not in curr.children:
                return False
            else:
                curr = curr.children[ch]
                if curr.is_end:
                    return True
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
    def __init__(self, words: List[str]):
        self.history = \"\"
        self.map = {}
        
        for word in words:
            curr_node = self.map
            for letter in word[::-1]:
                if letter not in curr_node:
                    curr_node[letter] = {}
                curr_node = curr_node[letter]
            curr_node['#'] = {}

    def query(self, letter: str) -> bool:
        self.history += letter

        curr_node = self.map
        for l in self.history[::-1]:

            if l not in curr_node:
                return False
                    
            curr_node = curr_node[l]
        
            if '#' in curr_node:
                return True
        
        return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.words = words
        self.trie = {}
        self.history = ''
        for w in words:
            p = self.trie
            for c in w[::-1]:
                if c not in p: p[c] = {}
                p = p[c]
            p['#'] = w

    def query(self, letter: str) -> bool:
        self.history+=letter
        p = self.trie
        for c in self.history[::-1]:
            if c not in p: return False
            p = p[c]
            if '#' in p: return True
        return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    def __init__(self):
        self.root = TrieNode(\"\")
        
    def insert(self, word):
        current = self.root
        for c in word:
            if current.child[ord(c) - ord('a')] == None:
                current.child[ord(c) - ord('a')] = TrieNode(c)
            current = current.child[ord(c) - ord('a')]
        current.isEnd = True
        
    def contains(self, word):
        current = self.root
        for c in word:
            if current.child[ord(c) - ord('a')] == None:
                return False
            current = current.child[ord(c) - ord('a')]
        return current.isEnd
    
    def startsWith(self, word):
        current = self.root
        for c in word:
            if current.child[ord(c) - ord('a')] == None:
                return False
            current = current.child[ord(c) - ord('a')]
        return True
              
class TrieNode:
    def __init__(self, char):
        self.val = char
        self.isEnd = False
        self.child = [None for i in range(27)]
    

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        for word in words:
            self.trie.insert(word[::-1])
        self.buff = []

    def query(self, letter: str) -> bool:
        self.buff.append(letter)
        n = len(self.buff)
        s = \"\"
        for i in range(n - 1, max(n - 2000, -1), -1):
            s += self.buff[i]
            if not self.trie.startsWith(s):
                return False
            if self.trie.contains(s):
                return True
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker(object):
    def __init__(self, words):
        self.words = set(words)
        self.added_chars = \"\"
        self.terminal_chars = set()
        for w in words:
            self.terminal_chars.add(w[-1])

    def query(self, char):
        self.added_chars += char
        if char in self.terminal_chars:
            for w in self.words:
                if self.added_chars.endswith(w):
                    return True
        return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class node:
    def __init__(self):
        self.isword = False
        self.child = defaultdict(node)
        
class StreamChecker:
    def __init__(self, words: List[str]):
        self.history = \"\"
        self.root = node()
        
        for w in words:
            cur = self.root
            for c in w[::-1]:
                cur = cur.child[c]
            cur.isword = True
        

    def query(self, letter: str) -> bool:
        cur = self.root
        self.history += letter
        for c in self.history[::-1]:
            if c not in cur.child: return False
            cur = cur.child[c]
            if cur.isword: return True
            
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.history = \"\"
        # Build a trie
        self.map = {}
        for word in words:
            curr_node = self.map
            for letter in word[::-1]:
                if letter not in curr_node:
                    curr_node[letter] = {}
                curr_node = curr_node[letter]
            curr_node['#'] = {}

    def query(self, letter: str) -> bool:
        \"\"\"Return true if letter completes a word in words.\"\"\"
        self.history += letter
        curr_node = self.map
        for char in self.history[::-1]:
            if char not in curr_node:
                return False
            curr_node = curr_node[char]
            if '#' in curr_node:
                return True
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.dict = {}
        self.word = \"\"
        for i in range(len(words)):
            lastChar = words[i][-1]
            if lastChar in self.dict:
                self.dict[lastChar].append(words[i])
            else:
                self.dict[lastChar] = [words[i]]
        #print (self.dict)  

    def query(self, letter: str) -> bool:      
        self.word += letter
        count = len(self.word) 
        if letter in self.dict:
            if letter in self.dict[letter]:
                return True
            else:
                lWords = list(self.dict[letter])                 
                for i in range(len(lWords)):
                    length = len(lWords[i])
                    #print (letter, self.word, self.word[count-length:], lWords[i])
                    if count >= length and self.word[count-length:] == lWords[i]:
                        #print (letter, lWords[i])
                        return True
       
        return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

from functools import reduce
from collections import deque, defaultdict


class StreamChecker:

    def __init__(self, words: List[str]):
        self.words = words
        self.stream = ''
        self.letters, self.end_letter = self.prep()

    def prep(self):
        letters = set()
        end_letter = defaultdict(list)
        self.words.sort(key=lambda x: len(x))
        for i, word in enumerate(self.words):
            letters = letters.union(set(word))
            end_letter[word[-1]].append(i)
        return letters, end_letter

    def query(self, letter: str) -> bool:
        self.stream += letter
        if letter not in self.letters:
            return False
        for i in self.end_letter.get(letter, []):
            if len(self.stream) < len(self.words[i]):
                return False
            if self.stream[-len(self.words[i]):] == self.words[i]:
                return True
        return False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.history = \"\"
        self.map = {}
        
        for word in words:
            curr_node = self.map
            for letter in word[::-1]:
                if letter not in curr_node:
                    curr_node[letter] = {}
                curr_node = curr_node[letter]
            curr_node['#'] = {}
        print(self.map)

    def query(self, letter: str) -> bool:
        self.history += letter

        curr_node = self.map
        for l in self.history[::-1]:

            if l not in curr_node:
                return False
                    
            curr_node = curr_node[l]
        
            if '#' in curr_node:
                return True
        
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Trie:
    def __init__(self):
        self.is_word = False
        self.child = defaultdict(Trie)
    
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie() # root
        self.stream = ''
        for w in words:
            cur_node = self.trie
            for c in w[::-1]:
                # reverse char in word
                cur_node = cur_node.child[c]
            # last letter of word
            cur_node.is_word = True
    
                

    def query(self, letter: str) -> bool:

        self.stream += letter
        node = self.trie
        for c in reversed(self.stream):
            if c not in node.child:
                return False
            node = node.child[c]
            if node.is_word:
                return True
        return False

            

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import defaultdict

class TrieNode:
    def __init__(self):
        self.children=defaultdict(TrieNode)
        self.is_end=False


class Trie:
    def __init__(self):
        self.root=TrieNode()
        
    def insert(self,s):
        tem=self.root
        for i in s:
            tem=tem.children[i]
        tem.is_end=True
        
    def search(self,s):
        tem=self.root
        for i in range(len(s)):
            node=tem.children.get(s[i])
            if(node==None):
                return False
            if(node.is_end):
                return True
            
            tem=node
            
        return tem.is_end
        


class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie=Trie()
        self.ls=words
        for i in self.ls:
            self.trie.insert(i[::-1])
        self.q=\"\"
        

    def query(self, letter: str) -> bool:
        self.q+=letter
        return self.trie.search(self.q[::-1])

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie={}
        for i in words:
            k=self.trie
            j=i[::-1]
            for f in j:
                if f not in k:
                    k[f]={}
                k=k[f]
            k['$']=1
        print(self.trie)
        self.past=\"\"

    def query(self, letter: str) -> bool:
        self.past+=letter
        ans=True
        k=self.trie
        for i in self.past[::-1]:
            if i not in k:
                ans=False
                break
            k=k[i]
            if '$' in k:
                break
        if ans and '$' in k:
            return True
        return False
                
            
            
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        for w in words:
            self.trie.insert(w[::-1])
        self.history = ''
    def query(self, letter: str) -> bool:
        self.history += letter
        return self.trie.search(self.history[::-1])


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Node():
    def __init__(self):
        self.children = {}
        self.exist = 0
    
    
class Trie():
    def __init__(self):
        self.root = Node()
    
    def insert(self, w):
        curr_node = self.root
        for c in w:
            if c not in curr_node.children:
                curr_node.children[c] = Node()
            curr_node = curr_node.children[c]
        curr_node.exist = 1
    
    def search(self, w):
        curr_node = self.root
        for c in w:
            if c not in curr_node.children:
                return False
            curr_node = curr_node.children[c]
            if curr_node.exist:
                return True
        return False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        for word in words:
            self.trie.add(word[::-1])
        self.stream = ''

    def query(self, letter: str) -> bool:
        node = self.trie.root
        self.stream += letter
        for char in self.stream[::-1]:
            if char in node.c:
                node = node.c[char]
            else:
                break
            if node.isword:
                return True
        return False
        
        
class Trie:
    def __init__(self):
        self.root = TrieNode('')
    
    def add(self, word):
        node = self.root
        for char in word:
            if char not in node.c:
                node.c[char] = TrieNode(char)
            node = node.c[char]
        node.isword = True
            

class TrieNode:
    def __init__(self, v):
        self.v = v
        self.c = dict()
        self.isword = False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.history = \"\"
        self.map = {}
        
        for word in words:
            curr_node = self.map
            for letter in word[::-1]:
                if letter not in curr_node:
                    curr_node[letter] = {}
                curr_node = curr_node[letter]
            curr_node['#'] = {}
        
    def query(self, letter: str) -> bool:
        self.history += letter
        curr_node = self.map
        for letter in self.history[::-1]:
            if letter not in curr_node:
                return False
            curr_node = curr_node[letter]
            if '#' in curr_node:
                return True
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

from collections import defaultdict

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


class StreamChecker:

    def __init__(self, words: List[str]):
        self.root=TrieNode()
        self.mx_length=0
        for word in words:
            self.insert(word[::-1])
            self.mx_length=max(self.mx_length,len(word))
        
        self.buffer=''
        
        
    def insert(self,word):
        curr_node=self.root
        for ch in word:
            curr_node=curr_node.children[ch]
        curr_node.isWord=True
            
    def search(self,word):
        cur_node=self.root
        for ch in word:
            cur_node=cur_node.children.get(ch)
            if not cur_node:
                return False
            if cur_node.isWord:
                return True
        
        return False
        
        

    def query(self, letter: str) -> bool:
        self.buffer+=letter
        return self.search(self.buffer[::-1])


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    
    def __init__(self):
        self.dict = {}
        self.leaf = False
        
    def addWord(self,word):
        newTrie = Trie()
        if word[0] in self.dict:
            newTrie = self.dict[word[0]]
        else:
            self.dict[word[0]] = newTrie
        if len(word) == 1:
            newTrie.leaf = True
        else:
            newTrie.addWord(word[1:])
            
    
# class Node:
    
#     def __init__(self,val,left=None,right=None):
#         self.val = val
#         self.left = left; self.right = right
    
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.queryStr = ''
        for word in words:
            self.trie.addWord(word[::-1])
        #print(self.trie)
        
    def query(self, letter: str) -> bool:
        self.queryStr += letter
        curTrie = self.trie
        #print(letter)
        for ch in self.queryStr[::-1]:
            #print('current ch : {}'.format(ch))
            if ch in curTrie.dict:
                curTrie = curTrie.dict[ch]
                if curTrie.leaf == True:
                    return True
                #print(curTrie.dict)
                #print(curTrie.leaf)
            else:
                #print('return false')
                return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        newwords = []
        for w in words:
            if w not in newwords:
                newwords.append(w)
        self.words = newwords
        print(\"number of words = \" + str(len(self.words)))
        self.check = \"\"



    def query(self, letter: str) -> bool:
        self.check += letter
        for word in self.words:
            if word[-1] != letter:
                continue
            if len(word) > len(self.check):
                continue

            if word == self.check[-1 * len(word):]:
                return True
        return False
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self, parent):
        self.parent = parent
        self.children = collections.defaultdict(lambda: TrieNode(self))
        self.c = None

class Trie:
    
    def __init__(self):
        self.root = TrieNode(None)
        self.ends = collections.defaultdict(list)
    
    def add(self, word):
        curr = self.root
        for c in word:
            curr = curr.children[c]
            curr.c = c
        if len(word) > 0:
            self.ends[word[-1]].append(curr)
        
    def isMember(self, letters):
        if letters[-1] not in self.ends:
            return False
        poss = self.ends[letters[-1]]
            
        for p in poss:
            curr = p
            index = len(letters) - 2
            while curr and index >= 0:
                curr = curr.parent
                if curr == self.root:
                    return True
                if curr.c != letters[index]:
                    curr = None
                index -= 1
            if index == -1 and curr != None and curr.parent == self.root:
                return True
        return False

        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        for w in words:
            self.trie.add(w)
        self.maxLen = max(list([len(x) for x in words]))
        self.queries = []

    def query(self, letter: str) -> bool:
        self.queries.append(letter)
        if len(self.queries) > self.maxLen:
            del self.queries[0]
        return self.trie.isMember(self.queries)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.stream = \"\"
        for word in words:
            curr = self.trie
            for w in word[::-1]:
                curr = curr.setdefault(w,{})
            curr['$'] = '$'
    def query(self, letter: str) -> bool:
        self.stream += letter
        curr = self.trie
        for s in self.stream[::-1]:
            if '$' in curr: return True
            if s not in curr: return False
            curr = curr[s]
        return '$' in curr
            

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

# 1032. Stream of Characters

# class TrieNode:
#     def __init__(self, val=None, isEnd=False):
#         self.val = val
#         self.isEnd = isEnd
#         self.next = {}

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.stream = deque([])

        for word in set(words):
            node = self.trie       
            for ch in word[::-1]:
                if not ch in node:
                    node[ch] = {}
                node = node[ch]
            node['$'] = word
        
        
    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        
        node = self.trie
        for ch in self.stream:
            if '$' in node:
                return True
            if not ch in node:
                return False
            node = node[ch]
        return '$' in node
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            trie = self.trie
            for letter in word[::-1]:
                if letter not in trie:
                    trie[letter] = {}
                trie = trie[letter]
            trie['$'] = ''
        print((self.trie))
        self.queue = deque()    
        self.max_len = max(len(word) for word in words)

    def query(self, letter: str) -> bool:
        self.queue.appendleft(letter)
        if len(self.queue) > self.max_len:
            self.queue.pop()
        trie = self.trie
        for letter in self.queue:
            trie = trie.get(letter)
            if trie is None:
                return False
            if '$' in trie:
                return True
        return False
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:


#     def __init__(self, words: List[str]):
#         self.root = {}
#         self.end = -1
#         for w in words:
#             self.insert(w)
#         self.qhist = ''

#     def insert(self, word):
#         curNode = self.root
#         for c in word[::-1]:
#             if not c in curNode:
#                 curNode[c] = {}
#             curNode = curNode[c]
#         curNode[self.end] = True

#     def query(self, letter: str) -> bool:
#         self.qhist += letter
#         curNode = self.root
#         for c in self.qhist[::-1]:
#             if not c in curNode:
#                 return False
#             curNode = curNode[c]
#             if self.end in curNode:
#                 return True
    def __init__(self, words: List[str]):
        self.dic = {}
        for word in words:
            if word[-1] not in self.dic:
                self.dic[word[-1]] = [word[:-1]]
            else:
                self.dic[word[-1]].append(word[:-1])
        
        self.string = \"\"

    def query(self, letter: str) -> bool:
        self.string += letter
        if letter in self.dic:
            for word in self.dic[letter]:
                length = len(word) + 1
                complete_word = word + letter
                if len(self.string) >= length and complete_word == self.string[- length:]:
                    return True
            return False
        else:
            return False



# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self):
        self.nodes = dict()
        self.is_leaf = False
    def insert(self,word):
        curr = self
        for char in word:
            if char not in curr.nodes:
                curr.nodes[char] = TrieNode()
            curr = curr.nodes[char]
        curr.is_leaf = True
    def check(self,word):
        curr = self
        for c in word:
            if c not in curr.nodes:
                return False
            curr = curr.nodes[c]
            if curr.is_leaf:
                return True
        return False
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = TrieNode()
        for word in words:
            self.root.insert(word[::-1])
        self.sb = ''
    def query(self, letter: str) -> bool:
        self.sb += letter
        node = self.root
        return node.check(self.sb[::-1])

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.children = {}
        self.found = False
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = TrieNode()
        self.term = \"\"
        for w in words:
            cur = self.root
            for c in w[::-1]:
                if c not in cur.children:
                    cur.children[c] = TrieNode()
                cur = cur.children[c]
            cur.found = True

    def query(self, letter: str) -> bool:
        self.term += letter
        cur = self.root
        for c in self.term[::-1]:
            if cur.found:
                return True
            if c not in cur.children:
                break
            cur = cur.children[c]
        if cur.found:
            return True
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamTrie:

    def __init__(self, mychar='ROOT'):
        self.char = mychar
        self.children = {}
        self.mass = 0
        # START WITH EMPTY STRING?
        # self.add('') ??
        if mychar=='ROOT':
            self.max_len = 0
        #self.
    
    #def checkChar(self, nxtChr):
            
    def add(self, word, top_level=True):
        if len(word) == 0:
            self.children['END'] = True
        else:
            self.mass += 1
            c = word[0]
            if not c in self.children:
                self.children[c] = StreamTrie(c)
            self.children[c].add(word[1:],top_level=False)

        if top_level:
            self.max_len = max(self.max_len,len(word))

    def get_max_len(self):
        return self.max_len

    def matches(self,word):
        if len(word) == 0 and 'END' in self.children:
            return True
        if len(word) > 0 and word[0] in self.children:
            return self.children[word[0]].matches(word[1:])
        return False

    def all_matches_from_beginning(self, query_string):
        match_list = []
        first = query_string[0]
        if first in self.children:
            self.children[first]._match_all(query_string,0,match_list)
        return match_list

    def _match_all(self,query_string,cur_ind,match_set):
        #if len(match_set) > 0
        if 'END' in self.children:
            match_set.append(query_string[:(cur_ind+1)])
        #if query_string[ind] == self.char:
        if cur_ind+1 < len(query_string):
            nxt = query_string[cur_ind+1]
            if nxt in self.children:
                self.children[nxt]._match_all(query_string,cur_ind+1,match_set)
        # return

    def any_match_from_beginning(self, query_string):
        #print(query_string)
        return self.children[query_string[0]]._match_any(query_string,0) if query_string[0] in self.children else False
    
    def _match_any(self,query_string,cur_ind):
        #if len(match_set) > 0
        if 'END' in self.children:
            return True
        if cur_ind+1 < len(query_string) and query_string[cur_ind+1] in self.children:
            return self.children[query_string[cur_ind+1]]._match_any(query_string,cur_ind+1)
        else:
            return False

    def __repr__(self):
        return self.__str__()

    def __str__(self):
        if 'END' in self.children:
            return f'[{self.char}*]'

        s = f'[{self.char}:{self.mass} '
        if self.char == 'ROOT':
            s = f'Trie({self.mass} '

        kids = []
        for k in self.children:
            if not k == 'END':
                kids.append(str(self.children[k]))
        s += ', '.join(kids)

        s += ')' if self.char == 'ROOT' else ']'

        return s


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = StreamTrie()
        self.longest = 0
        for word in words:
            self.trie.add(word[::-1])
            if len(word) > self.longest:
                self.longest = len(word)
        self.stream = deque()

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        if len(self.stream) > self.longest:
            self.stream.pop()
        #print(self.stream)
        return self.trie.any_match_from_beginning(''.join(self.stream))
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


# build a trie for sure.
# think about the reverse word (aka the order trie is queried is reverse) here, seems we have to build it in reverse order ??

class StreamChecker:
    def __init__(self, words: List[str]):
        
        self.map = dict()
        self.max_len = max([len(i) for i in words])
        self.history = \"\"
        
        for word in words:
            node = self.map
            for letter in word[::-1]:
                if letter not in node:
                    node[letter] = dict()
                node = node[letter]
            node['$'] = {}
            
    def query(self, letter: str) -> bool:
        self.history += letter
        node = self.map
        
        for l in self.history[::-1]:
            if l not in node: 
                return False
            node = node[l]
            if '$' in node:
                return True
        return False
            

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

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

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

    def insert(self, word: str) -> None:
        \"\"\"
        Inserts a word into the trie.
        \"\"\"
        node = self.root
        for ch in word:
            node = node.children[ch]
        node.isWord = True

    def search(self, word: str) -> bool:
        \"\"\"
        Returns if the word is in the trie.
        \"\"\"
        node = self.root
        for ch in word:
            if ch not in node.children:
                break
            node = node.children.get(ch)
            if node.isWord:
                return True
        return False
class StreamChecker:

    def __init__(self, words: List[str]):
        self.words = words
        self.chars = ''
        self.trie = Trie()
        for word in words:
            self.trie.insert(word[::-1])

    def query(self, letter: str) -> bool:
        self.chars += letter
        return self.trie.search(self.chars[::-1])

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.dic = {}
        for word in words:
            if word[-1] not in self.dic:
                self.dic[word[-1]] = [word[:-1]]
            else:
                self.dic[word[-1]].append(word[:-1])
        self.string = \"\"
        

    def query(self, letter: str) -> bool:
        self.string += letter
        if letter in self.dic:
            for word in self.dic[letter]:
                length = len(word) + 1
                complete_word = word + letter
                if len(self.string) >= length and complete_word == self.string[- length:]:
                    return True
            return False
        else:
            return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

from collections import defaultdict


class TrieNode:
    def __init__(self, letter):
        self.letter = letter
        self.children = {}
        self.end_of_word = False

        
class Trie:
    def __init__(self):
        self.root = TrieNode(\"*\")
        
    def insert(self, word):
        word = word[::-1]
        curr_node = self.root
        
        for letter in word:
            if letter not in curr_node.children:
                curr_node.children[letter] = TrieNode(letter)
                
            curr_node = curr_node.children[letter]
        
        curr_node.end_of_word = True
        
    def word_exists(self, word):
        word = word[::-1]
        curr_node = self.root
        
        for letter in word:
            if letter not in curr_node.children:
                break
            
            curr_node = curr_node.children[letter]
            
            if curr_node.end_of_word:
                return True
        
        return False
            
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.string = \"\"
        self.trie = Trie()
        
        for word in words:
            self.trie.insert(word)
              

    def query(self, letter: str) -> bool:
        self.string += letter
        
        return self.trie.word_exists(self.string)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.size = len(max(words, key=len))
        self.buffer = \"\"
        self.words = [word[::-1] for word in words]
        self.words.sort() 
        
    def query(self, letter: str) -> bool:
        print('Start\
')
        self.buffer += letter
        # self.buffer = self.buffer[-self.size:] # trim buffer
        
        for word in self.words:  
            buffer_strip = self.buffer[-len(word):]
            if word[::-1] == buffer_strip:
                return True
            if(word[0] > letter):
                return False


        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Trie:
    def __init__(self):
        self.chars = {}

    def add(self, word):
        cur = self.chars
        for ch in word:
            cur.setdefault(ch, {})
            cur = cur[ch]
        cur['#'] = '#'

    def find(self, word):

        cur = self.chars
        for ch in word:
            if ch not in cur:
                return False
            cur = cur[ch]
        return '#' in cur


class StreamChecker:
    def __init__(self, words):
        self.trie = Trie()
        for word in words:
            self.trie.add(reversed(word))
        self.max_len = max(words,key=lambda x:len(x))    
        self.buf = []

    def query(self, letter):
        self.buf.append(letter)
        cur = self.trie.chars
        for i in range(len(self.buf) - 1, -1, -1):
            ch = self.buf[i]
            if ch not in cur:
                return False
            if '#' in cur[ch]:
                return True
            cur = cur[ch]
        return False

class StreamChecker:

    def __init__(self, words: List[str]):
        
        self.curr = ''
        self.words = words
        temp = []
        for w in words:
            temp.append(w[-1])
        self.last = temp
        
        self.MAX = 1
        self.lenth = []
        self.storage = collections.defaultdict(list)
        for w in words:
            if len(w) not in self.lenth:
                self.lenth.append(len(w))
            self.storage[len(w)].append(w)
            self.MAX = max(self.MAX, len(w))

        
    def query(self, letter: str) -> bool:
        
        # print('start', letter, self.curr)
        
        if len(self.curr) < self.MAX:
            self.curr += letter
        elif len(self.curr) == self.MAX:
            self.curr = self.curr[1:] + letter
            
        # print(letter, self.curr)
            
        if letter in self.last:   
            
            # print('in')
            
            for i in range(1, len(self.curr)+1):
                # print(i, self.curr, self.curr[-i:])
                if self.curr[-i:] in self.storage[i]:
                    return True
                else:
                    continue  
            return False
        
        else:
            return False
        
        
        
    


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            trie = self.trie
            for letter in word:
                trie = trie.setdefault(letter, {})
            trie[' '] = {}
        self.check = []

    def query(self, letter: str) -> bool:
        self.check.append(self.trie)
        self.check = [trie[letter] for trie in self.check if letter in trie]
        for trie in self.check:
            if ' ' in trie: return True
        return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)



        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.dic = {}
        for word in words:
            if word[-1] not in self.dic:
                self.dic[word[-1]] = [word[:-1]]
            else:
                self.dic[word[-1]].append(word[:-1])
        
        self.string = \"\"

    def query(self, letter: str) -> bool:
        self.string += letter
        if letter in self.dic:
            for word in self.dic[letter]:
                length = len(word) + 1
                complete_word = word + letter
                if len(self.string) >= length and complete_word == self.string[- length:]:
                    return True
            return False
        else:
            return False

        



class StreamChecker:

    def __init__(self, words: List[str]):
        self.words = set(words)
        self.last_letters = set([word[-1] for word in words])
        self.max_length = max(map(len, self.words))
        self.history = []

    def query(self, letter: str) -> bool:
        if letter in self.words:
            return True
        self.history.append(letter)
        if letter in self.last_letters:
            word = \"\"
            for i in range(min(self.max_length, len(self.history))):
                word = self.history[-1 * i - 1] + word
                if word in self.words:
                    return True
        
        while len(self.history) > self.max_length:
            self.history.pop(0)
        
        return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Node:
    def __init__(self):
        self.children = {}
        self.isLeaf = False
class Trie:
    def __init__(self):
        self.root = Node()
        
    def addWord(self, word):
        node = self.root
        for char in word:
            if char not in node.children:
                node.children[char] = Node()
            node = node.children[char]
        node.isLeaf = True
        
    def isWord(self, word):
        node = self.root
        for char in word:
            if char not in node.children:
                return False
            node = node.children[char]
        return node.isLeaf
    
    def isPrefix(self, word):
        node = self.root
        for char in word:
            if char not in node.children:
                return False
            node = node.children[char]
        return True
            


class StreamChecker:

    def __init__(self, words: List[str]):
        self.letters = []
        self.trie = Trie()
        for word in words:
            self.trie.addWord(word[::-1])
        
            
    def query(self, letter: str) -> bool:
        self.letters.insert(0, letter)
        
        right = 0
        
        while right < len(self.letters):
            string = \"\".join(self.letters[:right+1])
            if self.trie.isPrefix(string):
                if self.trie.isWord(string):
                    return True
                right += 1
            else:
                return False
        
        return False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.words = words
        self.trie = {}
        self.history = ''
        for w in words:
            p = self.trie
            for c in w[::-1]:
                if c not in p: p[c] = {}
                p = p[c]
            p['#'] = ''

    def query(self, letter: str) -> bool:
        self.history+=letter
        p = self.trie
        for c in self.history[::-1]:
            if c not in p: return False
            p = p[c]
            if '#' in p: return True
        return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.Trie = {}
        for word in words:
            trieNode = self.Trie
            for ch in word[::-1]:
                if ch not in trieNode:
                    trieNode[ch] = {}
                trieNode = trieNode[ch]
            trieNode['END'] = True
        self.letter = ''
        

    def query(self, letter: str) -> bool:
        self.letter += letter
        trieNode = self.Trie
        for ch in self.letter[::-1]:
            if ch not in trieNode:
                return False
            trieNode = trieNode[ch]
            if 'END' in trieNode:
                return True
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.history = \"\"
        self.map = {}
        
        for word in words:
            curr_node = self.map
            for letter in word[::-1]:
                if letter not in curr_node:
                    curr_node[letter] = {}
                curr_node = curr_node[letter]
            curr_node['#'] = {}

    def query(self, letter: str) -> bool:
        self.history += letter

        curr_node = self.map
        for l in self.history[::-1]:

            if l not in curr_node:
                return False
                    
            curr_node = curr_node[l]
        
            if '#' in curr_node:
                return True
        
        return False
        
        
        
        
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.words=set(words)
        self.maxx = len(max(self.words,key=len))
        self.tails = {word[-1] for word in words}
        self.qs = ''
    

    def query(self, letter: str) -> bool:
        self.qs +=letter
        if len(self.qs)>self.maxx:
            self.qs = self.qs[1:]
        if letter not in self.tails:
            return False
        N = len(self.qs)
        return any((self.qs[i:N] in self.words for i in range(N)))
        # return letter in self.words


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
        
    def __init__(self, words: List[str]):
        self.history = \"\"
        self.map = {}
        
        for word in words:
            curr_node = self.map
            for letter in word[::-1]:
                if letter not in curr_node:
                    curr_node[letter] = {}
                curr_node = curr_node[letter]
            curr_node['#'] = {}

    def query(self, letter: str) -> bool:
        self.history += letter

        curr_node = self.map
        for l in self.history[::-1]:

            if l not in curr_node:
                return False
                    
            curr_node = curr_node[l]
        
            if '#' in curr_node:
                return True
        
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = {}
        self.end = '*'
        for word in words:
            self.insert(word[::-1])
        self.history = \"\"
        print(self.root)
    def query(self, letter: str) -> bool:
        self.history += letter
        return self.search(self.history[::-1])
            
        
    
    def insert(self, words:str) -> None:
        current = self.root
        for char in words:
            if char not in current:
                current[char] = {}
            current = current[char]
        current[self.end] = True
    
    def search(self, string:str) -> bool:
        current = self.root
        for char in string:
            if self.end in current:
                return True
            if char in current:
                current = current[char]
            else:
                return False
        return self.end in current
                

        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.words = set(words)
        self.last_letters = set([word[-1] for word in words])
        self.max_length = max(map(len, self.words))
        self.history = []

    def query(self, letter: str) -> bool:
        if letter in self.words:
            return True
        self.history.append(letter)
        if letter in self.last_letters:
            word = \"\"
            for i in range(min(self.max_length, len(self.history))):
                word = self.history[-1 * i - 1] + word
                if word in self.words:
                    return True
        
        while len(self.history) > self.max_length:
            self.history.pop(0)
        
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Trie:
    
    def __init__(self):
        self.dict = {}
        self.leaf = False
        
    def addWord(self,word):
        curTrie = self
        for ch in word:
            if ch not in curTrie.dict:
                curTrie.dict[ch] = Trie()
            curTrie = curTrie.dict[ch]
        curTrie.leaf = True
        
    def search(self,query):
        curTrie = self
        # print('query : {}'.format(query))
        for ch in query:
            if ch in curTrie.dict:
                # print('ch : {}'.format(ch))
                # print('dict : {}'.format(curTrie.dict))
                curTrie = curTrie.dict[ch]
                if curTrie.leaf == True:
                    # print('return True')
                    return True
            else:
                # print('return False')
                return False
        return False
            
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.queryStr = ''
        for word in words:
            self.trie.addWord(word[::-1])
        
    def query(self, letter: str) -> bool:
        self.queryStr += letter
        curTrie = self.trie
        return curTrie.search(self.queryStr[::-1])

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.history = \"\"
        self.li = {}
        
        for word in words:
            curr = self.li
            for c in word[::-1]:
                if c not in curr:
                    curr[c] = {}
                curr = curr[c]
            
            curr[\"#\"] = {}

    def query(self, letter: str) -> bool:
        self.history += letter
        
        curr = self.li
        for l in self.history[::-1]:
            if l not in curr:
                return False
            
            if \"#\" in curr[l]:
                return True
            
            curr = curr[l]
        
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.tracker=\"\"
        self.map={}
        
        for word in words:
            curr=self.map
            for letter in word[::-1]:
                if letter not in curr:
                    curr[letter]={}
                curr=curr[letter]
            curr[\"$\"]={}
                
                    
                
    def query(self, letter: str) -> bool:
        
        self.tracker+=letter
        curr=self.map
        for l in self.tracker[::-1]:
            if l not in curr:
                return False
            curr=curr[l]
            
            if \"$\" in curr:
                return True
        
        return False
            
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie=defaultdict(dict)
        for word in words:
            node=self.trie
            for i in word[::-1]:
                if i not in node:
                    node[i]={}
                node=node[i]
            node['#']=word
        self.q=''

    def query(self, letter: str) -> bool:
        self.q += letter
        node=self.trie
        for i in self.q[::-1]:
            if '#' in node:
                return True
            if i not in node:
                return False            
            node=node[i]
        return '#' in node


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.stream = ''
        self.trie = {}
        
        # Initialize trie with words
        curr = self.trie
        for word in words:
            # Add reverse of word
            for char in word[::-1]:
                curr.setdefault(char, {})
                curr = curr[char]
            curr['end'] = True
            curr = self.trie
            
        # print(self.trie)
        
    def query(self, letter: str) -> bool:
        self.stream += letter
        
        def _search(string, curr):
            if 'end' in curr:
                return True
            
            if string and string[0] in curr:
                return _search(string[1:], curr[string[0]])
            
            return False
        
        
        return _search(self.stream[::-1], self.trie)

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    def __init__(self):
        self.child = {}
        self.isWord = False

    def add(self, s):
        t = self
        for c in s:
            if c not in t.child:
                t.child[c] = Trie()
            t = t.child[c]
        t.isWord = True

    def check(self, s):
        t = self
        for c in s:
            if c not in t.child:
                return False
            t = t.child[c]
            if t.isWord:
                return True
        return t.isWord

class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.cache = \"\"
        self.visited = {}
        for s in words:
            self.trie.add(s[::-1])

    def query(self, letter: str) -> bool:
        self.cache = self.cache + letter
        return self.trie.check(self.cache[::-1])
        
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

from collections import defaultdict
class TrieNode:
    def __init__(self):
        self.nexts = defaultdict(TrieNode)
        self.isword = False

class Trie:
    def __init__(self, words):
        self.root = TrieNode()
        for w in words:
            self.insert(w[:: -1])
    
    def insert(self, w):
        cur = self.root
        for c in w:
            cur = cur.nexts[c]
        cur.isword = True
    
    def search(self, w):
        cur = self.root
        for i in range(len(w) - 1, -1, -1):
            if w[i] in cur.nexts:
                cur = cur.nexts[w[i]]
                if cur.isword: return True
            else:
                return False
        return cur.isword
        
class StreamChecker:
    def __init__(self, words: List[str]):
        # Time: O(WQ), W is the maximum length of all words, Q is number of calls of function query
        self.t = Trie(words)
        self.cache = list()

    def query(self, letter: str) -> bool:
        self.cache.append(letter)
        return self.t.search(self.cache)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.children = collections.defaultdict(TrieNode)
        self.isWord = False
        
class Trie:
    def __init__(self):
        self.root = TrieNode()
        
    def insert(self, word):
        p = self.root
        for w in word[::-1]:
            if w not in p.children:
                p.children[w] = TrieNode()
            p = p.children[w]
        p.isWord = True

    def search(self, word):
        p = self.root
        for w in word[::-1]:
            if w not in p.children:
                break
            p = p.children[w]
            if p.isWord:
                return True
        return False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        for word in words:
            self.trie.insert(word)
        self.letters = ''

    def query(self, letter: str) -> bool:
        self.letters += letter
        return self.trie.search(self.letters)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.history = \"\"
        self.map = {}
        
        for word in words:
            curr_node = self.map
            for letter in word[::-1]:
                if letter not in curr_node:
                    curr_node[letter] = {}
                curr_node = curr_node[letter]
            curr_node['#'] = {}

    def query(self, letter: str) -> bool:
        self.history += letter

        curr_node = self.map
        for l in self.history[::-1]:

            if l not in curr_node:
                return False
                    
            curr_node = curr_node[l]
        
            if '#' in curr_node:
                return True
        
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

from collections import deque
class StreamChecker:

    def __init__(self, words: List[str]):
        self.data_set,self.end_chars, self.start_chars, self.min_len, self.max_len = self._get_set_min_max_len(words)
        self.queue = list()
        
    
    @staticmethod
    def _get_set_min_max_len(words):
        data_set = set(words)
        min_len = 10000
        max_len = 0
        end_chrs = set()
        start_chrs = set()
        for w in words:
            min_len = min(min_len, len(w))
            max_len = max(max_len, len(w))
            end_chrs.add(w[-1])
            start_chrs.add(w[0])
        return data_set, end_chrs,start_chrs, min_len, max_len
    
    def check_if_word_exists(self):
        c_l = len(self.queue)
        start_idx = c_l - self.min_len
        if start_idx >= 0:
            c_w = \"\".join(self.queue[k] for k in range(start_idx+1, c_l))
            for i in range(start_idx, max(-1, c_l - self.max_len-1), -1):
                c_w = f\"{self.queue[i]}{c_w}\"
                if self.queue[i] not in self.start_chars:
                    continue
                if c_w in self.data_set:
                    return True
        else:
            return False
        

    def query(self, letter: str) -> bool:
        # if len(self.queue) >= self.max_len:
        #     self.queue.popleft()
        self.queue.append(letter)
        if letter in self.end_chars:
            return self.check_if_word_exists()
        else:
            return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.d = dict()
        for word in words:
            cur_d = self.d
            for ch in word[::-1]:
                if ch in cur_d:
                    cur_d = cur_d[ch]
                else:
                    cur_d[ch] = {}
                    cur_d = cur_d[ch]
            cur_d['end'] = True
        self.query_cache = ''

    def query(self, letter: str) -> bool:
        self.query_cache += letter
        cur_d = self.d
        for ch in self.query_cache[::-1]:
            if ch in cur_d:
                if cur_d[ch].get('end'):
                    return True
                cur_d = cur_d[ch]
            else:
                break
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.history = \"\"
        self.map = {}
        
        for word in words:
            curr_node = self.map
            for letter in word[::-1]:
                if letter not in curr_node:
                    curr_node[letter] = {}
                curr_node = curr_node[letter]
            curr_node['#'] = {}

    def query(self, letter: str) -> bool:
        self.history += letter

        curr_node = self.map
        for l in self.history[::-1]:

            if l not in curr_node:
                return False
                    
            curr_node = curr_node[l]
        
            if '#' in curr_node:
                return True
        
        return False



# class StreamChecker {

#     private String[] words;
#     private int[] pointers;
#     private TrieNode root;
#     private Set<TrieNode> nodes;
    
#     public StreamChecker(String[] words) {
#         this.words = words;
#         this.pointers = new int[words.length];
#         this.root = new TrieNode(' ');
#         this.nodes = new HashSet<>();
#         for (String word : words) {
#             TrieNode node = this.root.insert(word);
#         }
#         this.nodes.add(this.root);
#     }
    
#     public boolean query(char letter) {
#         boolean found = false;
#         // System.out.println(this.nodes.size());
#         // System.out.println(letter);
#         Set<TrieNode> next = new HashSet<>();
#         for (TrieNode node : this.nodes) {
#             // System.out.println(\"checking node \" + node.ch);
#             if (node.children[letter - 'a'] != null) {
#                 // System.out.println(\"not null\");
#                 TrieNode matched = node.children[letter - 'a'];
#                 // System.out.println(\"matched ch \" + matched.ch);
#                 if (matched.isTerminal) {
#                     found = true;
#                     // System.out.println(found);
#                 } else {
#                     next.add(matched);
#                 }
#             } 
#         }
#         this.nodes.clear();
#         this.nodes.add(this.root);
#         this.nodes.addAll(next);
#         return found;
#     }
    
#     private class TrieNode {
#         char ch;
#         TrieNode[] children;
#         boolean isTerminal;
        
#         public TrieNode(char character) {
#             ch = character;
#             children = new TrieNode[26];
#             isTerminal = false;
#         };
        
#         TrieNode insert(String word) {
#             TrieNode node = this;
#             for (int i = 0; i < word.length(); i++) {
#                 char ch = word.charAt(i);
#                 TrieNode next = null;
#                 if (node.children[ch - 'a'] == null) {
#                     next = new TrieNode(ch);
#                     node.children[ch - 'a'] = next;
#                 } else {
#                     next = node.children[ch - 'a'];
#                 }
#                 if (i == word.length() - 1) next.isTerminal = true;
#                 node = next;
#             }
#             return node;
#         }
#     }
    
# //     public boolean query(char letter) {
# //         // System.out.println(\"query ===\");
# //         boolean found = false;
# //         for (int i = 0; i < pointers.length; i++) {
# //             // System.out.println(\"word is \" + this.words[i]);
# //             if (this.words[i].charAt(this.pointers[i]) == letter) {
# //                 // match
# //                 this.pointers[i]++;
# //                 // System.out.println(\"pointer++\");
# //                 if (this.pointers[i] == this.words[i].length()) {
# //                     this.pointers[i] = findPointer(this.words[i].substring(0, this.words[i].length() - 1), this.words[i].substring(1));
# //                     found = true;
# //                 }
# //             } else {
# //                 // mo match
# //                 if (this.pointers[i] == 0) continue;
# //                 this.pointers[i] = findPointer(this.words[i].substring(0, this.pointers[i]), this.words[i].substring(1, this.pointers[i]) + letter);
# //             }
# //         }
        
# //         // System.out.println(Arrays.toString(this.pointers));
        
# //         return found;
# //     }
    
# //     private int findPointer(String base, String sub) {
# //         //  System.out.println(\"findPointer\");
# //         // System.out.println(base);
# //         // System.out.println(sub);
        
# //         if (base.equals(sub)) {
# //             // System.out.println(base.length());
# //             return base.length();
# //         } 
        
# //         for (int i = base.length() - 1; i >= 1; i--) {
# //             if (base.substring(0, i).equals(sub.substring(base.length() - i))) {
# //                 // System.out.println(i);
# //                 return i;
# //             }
# //         }
        
# //         // System.out.println(0);
# //         return 0;
# //     }
# }

# /**
#  * Your StreamChecker object will be instantiated and called as such:
#  * StreamChecker obj = new StreamChecker(words);
#  * boolean param_1 = obj.query(letter);
#  */

from collections import defaultdict


class TrieNode(object):
    def __init__(self, value=None):
        # 值
        self.value = value
        # fail指针
        self.fail = None
        # 尾标志：标志为i表示第i个模式串串尾，默认为0
        self.tail = 0
        # 子节点，{value:TrieNode}
        self.children = {}


class Trie(object):
    def __init__(self, words):
        print(\"初始化\")
        # 根节点
        self.root = TrieNode()
        # 模式串个数
        self.count = 0
        self.words = words
        for word in words:
            self.insert(word)
        self.ac_automation()
        print(\"初始化完毕\")

    def insert(self, sequence):
        \"\"\"
        基操，插入一个字符串
        :param sequence: 字符串
        :return:
        \"\"\"
        self.count += 1
        cur_node = self.root
        for item in sequence:
            if item not in cur_node.children:
                # 插入结点
                child = TrieNode(value=item)
                cur_node.children[item] = child
                cur_node = child
            else:
                cur_node = cur_node.children[item]
        cur_node.tail = self.count

    def ac_automation(self):
        \"\"\"
        构建失败路径
        :return:
        \"\"\"
        queue = [self.root]
        # BFS遍历字典树
        while len(queue):
            temp_node = queue[0]
            # 取出队首元素
            queue.remove(temp_node)
            for value in temp_node.children.values():
                # 根的子结点fail指向根自己
                if temp_node == self.root:
                    value.fail = self.root
                else:
                    # 转到fail指针
                    p = temp_node.fail
                    while p:
                        # 若结点值在该结点的子结点中，则将fail指向该结点的对应子结点
                        if value.value in p.children:
                            value.fail = p.children[value.value]
                            break
                        # 转到fail指针继续回溯
                        p = p.fail
                    # 若为None，表示当前结点值在之前都没出现过，则其fail指向根结点
                    if not p:
                        value.fail = self.root
                # 将当前结点的所有子结点加到队列中
                queue.append(value)

    def search(self, text):
        \"\"\"
        模式匹配
        :param self:
        :param text: 长文本
        :return:
        \"\"\"
        p = self.root
        # 记录匹配起始位置下标
        # start_index = 0
        # 成功匹配结果集
        # rst = defaultdict(list)
        # for i in range(len(text)):
            # single_char = text[i]
        for single_char in text:
            rst=False
            while single_char not in p.children and p is not self.root:
                p = p.fail
            # 有一点瑕疵，原因在于匹配子串的时候，若字符串中部分字符由两个匹配词组成，此时后一个词的前缀下标不会更新
            # 这是由于KMP算法本身导致的，目前与下文循环寻找所有匹配词存在冲突
            # 但是问题不大，因为其标记的位置均为匹配成功的字符
            # if single_char in p.children and p is self.root:
                # start_index = i
            # 若找到匹配成功的字符结点，则指向那个结点，否则指向根结点
            if single_char in p.children:
                p = p.children[single_char]
            else:
                # start_index = i
                p = self.root
            temp = p
            while temp is not self.root:
                # 尾标志为0不处理，但是tail需要-1从而与敏感词字典下标一致
                # 循环原因在于，有些词本身只是另一个词的后缀，也需要辨识出来
                if temp.tail:
                    # rst[self.words[temp.tail - 1]].append((start_index, i))
                    rst=True
                temp = temp.fail
            yield rst
        # return rst

class StreamChecker:

    def __init__(self, words: List[str]):
        trie=Trie(words)
        self.chars=[]
        self.f=trie.search((x for x in self.chars))

    def query(self, letter: str) -> bool:
        self.chars.append(letter)
        return next(self.f)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self):
        self.children = dict()
        self.is_word = False
        
class Trie:
    def __init__(self):
        self.root = TrieNode()        
        
    def add_word(self, word):
        node = self.root
        for c in word:
            if c not in node.children:
                node.children[c] = TrieNode()    
            node = node.children[c]    
        node.is_word = True    
    
    def find_any(self, word):   
        node = self.root
        for c in word:
            if node.is_word: return True
            if c not in node.children: return False
            node = node.children[c]    
        return node.is_word
    
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        for word in words: self.trie.add_word(word[::-1])
        self.cur = ''    
        

    def query(self, letter: str) -> bool:
        self.cur += letter
        return self.trie.find_any(self.cur[::-1])
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode():
    def __init__(self):
        self.children = {}
        self.terminal = False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.queue = collections.deque()
        self.words = words
        
        self.root = TrieNode()
        
        for word in self.words:
            node = self.root
            
            for c in reversed(word):
                if c not in node.children:
                    node.children[c] = TrieNode()
                node = node.children[c]
                
            node.terminal = True
            
        

    def query(self, letter: str) -> bool:
        self.queue.appendleft(letter)
        
        node = self.root
        
        if letter in node.children:
            for l in self.queue:
                if l in node.children:
                    node = node.children[l]
                    if node.terminal:
                        return True
                else:
                    return False
                
        
        
        
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.dic={}
        for word in words:
            if word[-1] not in self.dic: self.dic[word[-1]]=[word[:-1]]
            else: self.dic[word[-1]].append(word[:-1])
        self.string=\"\"
        

    def query(self, letter: str) -> bool:
        self.string += letter
        if letter in self.dic:
            for word in self.dic[letter]:
                length=len(word)+1
                complete_word=word+letter
                if len(self.string) >= length and complete_word==self.string[-length:]: return True
            return False
        else: return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Trie:
    def __init__(self):
        self.dict = {};
        self.isEnd = False;
        
    
class StreamChecker:
    
    def __init__(self, words: List[str]):
        self.root = Trie()
        for i in words:self.insert(i[::-1]);
        self.cur = \"\";
    
    def insert(self,word):
        temp = self.root;
        for i in word:
            if(i not in temp.dict):temp.dict[i] = Trie();
            temp = temp.dict[i];
        temp.isEnd = True;
        return;
    
    def check(self,word):
        temp = self.root;
        word = word[::-1];
        for i in word:
            if(i not in temp.dict):return False;
            temp = temp.dict[i];
            if(temp.isEnd):return True;
        return temp.isEnd;
        
    def query(self, letter: str) -> bool:
        self.cur += letter;
        return self.check(self.cur);
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.stream = set(words)
        self.queries = ''

    def query(self, letter: str) -> bool:
        self.queries += letter
        for word in self.stream:
            if letter == word[~0]:
                if word == self.queries[-len(word):]:
                    return True
        return False
                
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


EOW = '*'
class StreamChecker:
    queries = []
    
    def __init__(self, words: List[str]):
        self.root = {}
        for word in words:
            node = self.root
            for c in word:
                if c in node:
                    node = node[c]
                else:
                    node[c] = {}
                    node = node[c]
            if not EOW in node:
                node[EOW] = True

    def query(self, letter: str) -> bool:
        self.queries = [q[letter] for q in self.queries if letter in q]
        if letter in self.root:
            self.queries.append(self.root[letter])
        
        return any([q for q in self.queries if EOW in q])
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = {}
        for word in words:
            curnode = self.root
            for ch in word:
                if ch not in curnode:
                    curnode[ch] = {}
                curnode = curnode[ch]
            curnode['is_end'] = True
        self.leads = [self.root] # the pointers to the threads we follow right now

    def query(self, letter: str) -> bool:
        next_leads = [self.root]
        found_word = False
        for lead in self.leads:
            if letter in lead:
                new_lead = lead[letter]
                next_leads.append(new_lead)
                if 'is_end' in new_lead:
                    found_word = True
        self.leads = next_leads
        return found_word

class StreamChecker:

    def __init__(self, words: List[str]):
        self.memo = {}
        self.words = set()
        words_ = [word[::-1] for word in set(words)]
        for word in words_:
            for i in range(len(word)-1):
                self.memo[word[:i+1]]=0
        
        for word in words_:
            self.memo[word]=1     
        
        self.hist = []
        
        #print(self.memo)
    
    def query(self, letter: str) -> bool:
        self.hist.append(letter)
        w = ''
        for i in range(len(self.hist)-1,-1,-1):
            w+=self.hist[i]
            #print(w)
            c = self.memo.get(w,None)
            if c is None:
                return False
            if c:
                return True
            
        return False


class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = {}
        self.END = '0'
        self.q = ''

        for word in words:
            curr_dict = self.root
            for letter in word[::-1]:  # save in reverse
                curr_dict = curr_dict.setdefault(letter, {})
            curr_dict[self.END] = self.END

    def query(self, letter: str) -> bool:
        self.q += letter
        curr_node = self.root
        for l in self.q[::-1]:  # search in reverse as well
            if l in curr_node:
                curr_node = curr_node.get(l)
            else:
                return False
            if self.END in curr_node:
                return True
        return False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.stream = \"\"
        self.dictionary = {}
        for word in words:
            location = self.dictionary
            for char in word[::-1]:
                if char not in location:
                    location[char] = {}
                location = location[char]
            location[\"goodbye\"] = True

    def query(self, letter: str) -> bool:
        self.stream += letter
        count = -1
        location = self.dictionary
        for char in self.stream[::-1]:
            if char in location:
                if \"goodbye\" in location[char]:
                    return True
                location = location[char]
                continue
            return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:
    
    def __init__(self, words: List[str]):
        self.d = {}
        self.queries = \"\"
        for word in words:
            self.d.setdefault(word[-1],set())
            self.d[word[-1]].add(word[:-1])
        

    def query(self, letter: str) -> bool:
        self.queries += letter
        if letter not in self.d: return False
        for word in self.d[letter]:
            if(len(self.queries)>=len(word)+1)and((word+letter) == self.queries[-(len(word)+1):]): return True
        return False
                
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.nodes = []
        for word in words:
            node = self.trie
            for char in word:
                if char not in node:
                    node[char] = {}
                node = node[char]
            node['end'] = True
        

    def query(self, letter: str) -> bool:
        self.nodes.append(self.trie)
        temp = False
        new_nodes = []
        
        for node in self.nodes:
            if letter in node:
                node = node[letter]
                if 'end' in node:
                    temp = True
                new_nodes.append(node)
        self.nodes = new_nodes
        return temp


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.words = list(set(words))
        self.chars = \"\"
        self._single_letters = set(w for w in words if len(w) == 1)
        self._last_letters = set(w[-1] for w in words)
        self._last_pairs = set(w[-2:] for w in words)
        
    def query(self, letter: str) -> bool:
        self.chars += letter
        if letter not in self._last_letters:
            return False
        if letter in self._single_letters:
            return True
        if self.chars[-2:] not in self._last_pairs:
            return False
        return any(self.chars.endswith(w) for w in self.words)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = {}
        self.memo = ''
        
        for w in words:
            ptr = self.root
            for c in w[::-1]:
                if c not in ptr:
                    ptr[c] = {}
                ptr = ptr[c]
            ptr['#'] = ''
        

    def query(self, letter: str) -> bool:
        self.memo += letter
        ptr = self.root
        for c in self.memo[::-1]:
            if c not in ptr:
                return False
            ptr = ptr[c]
            if '#' in ptr:
                return True
            
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import deque


class Node:

    def __init__(self) -> object:
        self.children = dict()
        self.isEND = False
        self.fail = None


class Trie:

    def __init__(self):
        self.root = Node()

    def insert(self, words):
        current_node = self.root
        for w in words:
            if current_node.children.get(w, None) is None:
                current_node.children[w] = Node()
            current_node = current_node.children[w]

        current_node.isEND = True
        # current_node.word = words

    def built_failover(self):

        q = deque()
        current = self.root
        for ch in self.root.children:
            self.root.children[ch].fail = self.root
            q.append(self.root.children[ch])
        while q:
            node = q.popleft()
            for ch in node.children:
                q.append(node.children[ch])
                failover = node.fail
                while True:
                    if failover is None:
                        node.children[ch].fail = self.root
                        break
                    if ch in failover.children:
                        node.children[ch].fail = failover.children[ch]
                        break
                    else:
                        failover = failover.fail

        

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        # self.q = deque()
        for word in words:
            self.trie.insert(word)
        self.trie.built_failover()
        self.curr = self.trie.root

        

    def query(self, letter: str) -> bool:
        result = False
        while True:
            if letter in self.curr.children:
                
                self.curr = self.curr.children[letter]
                
                if self.curr.isEND:
                    result = True
                if self.curr.fail !=None and self.curr.fail.isEND:
                    result = True
                break
            elif self.curr.fail == None:
                self.curr = self.trie.root
                break
            else:
                self.curr= self.curr.fail
        return result

        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        T=lambda: collections.defaultdict(T)
        self.trie=T()
        self.waiting=[]
        for w in words:
            d=self.trie
            for c in w:
                d=d[c]
            d=d['#']

    def query(self, letter: str) -> bool:
        self.waiting=[node[letter] for node in self.waiting+[self.trie] if letter in node]
        return any(d for d in self.waiting if '#' in d)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.letters = \"\"
        self.trie = {}
        for word in words:
            node = self.trie
            for ch in reversed(word):
                if ch not in node:
                    node[ch] = {}
                node = node[ch]
            node['$'] = '$'

    def query(self, letter: str) -> bool:
        self.letters += letter
        node = self.trie
        for ch in self.letters[::-1]:
            if ch not in node:
                return False
            node = node[ch]
            if '$' in node:
                return True
            
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.t={}
        for word in words:
            curr=self.t
            for i in word[::-1]:
                if i not in curr:
                    curr[i]={}
                curr=curr[i]
            curr['end']=True
        self.s=''
    def query(self, letter: str) -> bool:
        self.s+=letter
        curr=self.t
        for i in self.s[::-1]:
            if i not in curr:
                return False
            if i in curr:
                curr=curr[i]
            if 'end' in curr:
                return True
        return False
            
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.h = {}
        for word in words:
            curr_node = self.h           
            for x in range(len(word)):
                curr = word[x]
                if curr not in curr_node: curr_node[curr] = {}
                curr_node = curr_node[curr]
            curr_node[\"#\"] = True
        self.nodes = []

        
    def query(self, letter: str) -> bool:
        result = False
        self.nodes.append(self.h)
        new = []
        for node in self.nodes:
            if letter in node:
                node = node[letter]
                if \"#\" in node: result = True
                new.append(node)
        self.nodes = new     
        return result


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:


    def __init__(self, words: List[str]):
        self.root = {}
        self.end = -1
        for w in words:
            self.insert(w)
        self.qhist = ''

    def insert(self, word):
        curNode = self.root
        for c in word[::-1]:
            if not c in curNode:
                curNode[c] = {}
            curNode = curNode[c]
        curNode[self.end] = True

    def query(self, letter: str) -> bool:
        self.qhist += letter
        curNode = self.root
        for c in self.qhist[::-1]:
            if not c in curNode:
                return False
            curNode = curNode[c]
            if self.end in curNode:
                return True



# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.history = \"\"
        self.map = {}
        
        for word in words:
            curr_node = self.map
            for letter in word[::-1]:
                if letter not in curr_node:
                    curr_node[letter] = {}
                curr_node = curr_node[letter]
            curr_node['#'] = {}

    def query(self, letter: str) -> bool:
        self.history += letter

        curr_node = self.map
        for l in self.history[::-1]:

            if l not in curr_node:
                return False
                    
            curr_node = curr_node[l]
        
            if '#' in curr_node:
                return True
        
        return False



class TrieNode:
    def __init__(self):
        self.children = {}
        self.is_word = False
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = TrieNode()
        self.prefix = ''
        for word in words:
            node = self.root
            for c in word[::-1]:
                if c not in node.children:
                    node.children[c] = TrieNode()
                node = node.children[c]
            node.is_word = True

    def query(self, letter: str) -> bool:
        self.prefix += letter
        node = self.root
        for c in self.prefix[::-1]:
            if c not in node.children:
                return False
            node = node.children[c]
            if node.is_word:
                return True
        
        return False
        
        
                    
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    
    def __init__(self):
        
        self.children = {}
        self.isWord = False


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = TrieNode()
        self.prefix = \"\"
        ######################### SAVE IN REVERSED ORDER !!!!!!!!!!!!!!!!!!!!
        for word in words:
            cur = self.trie
            for char in word[::-1]:
                if not cur.children.get(char):
                    cur.children[char] = TrieNode()
                cur = cur.children[char]
            cur.isWord = True
            
    def query(self, letter: str) -> bool:
        self.prefix += letter
        cur = self.trie
        for char in self.prefix[::-1]:
            if not cur.children.get(char):
                return False
            cur = cur.children[char]
            if cur.isWord:
                return True
            

class StreamChecker:

    def __init__(self, words: List[str]):
        self.stream = \"\"
        self.max_len = max(len(word) for word in words)
        self.trie = {}
        self._build_trie(words)
        
    def query(self, letter: str) -> bool:
        self.stream += letter
        if len(self.stream) > self.max_len:
            self.stream = self.stream[1:]
            
        node = self.trie
        for char in self.stream[::-1]:
            if '$' in node:
                return True
            elif char not in node:
                return False
            else:
                node = node[char]
        
        return '$' in node
        
    def _build_trie(self, words: List[str]):
        for word in words:
            node = self.trie
            for char in word[::-1]:
                if char not in node:
                    node[char] = {}
                node = node[char]
            node['$'] = word
    

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:


    def __init__(self, words: List[str]):
        self.dic = {}
        
        for word in words:
            if word[-1] not in self.dic:
                self.dic[word[-1]] = [word[:-1]]
            else:
                self.dic[word[-1]].append(word[:-1])
        
        self.string = \"\"

    def query(self, letter: str) -> bool:
        self.string += letter
        if letter in self.dic:
            for word in self.dic[letter]:
                length = len(word) + 1
                complete_word = word + letter
                if len(self.string) >= length and complete_word == self.string[- length:]:
                    return True
        return False
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Trie:
    def __init__(self, word, end):
        self.children = word
        self.end = end
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie({}, False)
        for word in words:
            cur = self.trie
            for char in word[::-1]:
                if not char in cur.children:
                    cur.children[char]=Trie({},False)
                cur = cur.children[char]
            cur.end = True
        self.history = ''
            
    def query(self, letter: str) -> bool:
        # stream next letter if it's in children
        # new = self.trie
        # self.streamer.append(new)
        # i = 0
        # n = len(self.streamer)
        # res = False
        # while i<n:
        #     pointer = self.streamer.popleft()
        #     #print(pointer.children)
        #     if letter in pointer.children:
        #         self.streamer.append(pointer.children[letter])
        #         if pointer.children[letter].end:
        #             res = True
        #     i+=1
        self.history += letter
        streamer = self.trie
        for c in self.history[::-1]:
            if c not in streamer.children:
                return False
            elif streamer.children[c].end:
                return True
            streamer = streamer.children[c]
        return False
                             
                             

        

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.dict = set([w[::-1] for w in words])
        self.prev = \"\"
        

    def query(self, letter: str) -> bool:
        self.prev = letter + self.prev
        for s in self.dict:
            if self.prev.startswith(s): return True
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self):
        self.children = dict()
        self.is_word = False
        
class Trie:
    def __init__(self):
        self.root = TrieNode()        
        
    def add_word(self, word):
        node = self.root
        for c in word:
            if c not in node.children:
                node.children[c] = TrieNode()    
            node = node.children[c]    
        node.is_word = True    
        
    def find(self, word):   
        node = self.root
        for c in word:
            if c not in node.children: return False
            node = node.children[c]    
        return node.is_word
    
    def find_any(self, word):   
        node = self.root
        for c in word:
            if node.is_word: return True
            if c not in node.children: return False
            node = node.children[c]    
        return node.is_word
    
    def start_with(self, pattern):   
        node = self.root
        for c in pattern:
            if c not in node.children: return False
            node = node.children[c]    
        return True   
    
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        for word in words:
            self.trie.add_word(word[::-1])
        self.cur = ''    
        

    def query(self, letter: str) -> bool:
        self.cur += letter
        return self.trie.find_any(self.cur[::-1])
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.words=[word[::-1] for word in words]
        self.string=''
        self.l=0
        self.createTrie()
    def createTrie(self):
        for i in self.words:
            t=self.trie
            for j in i:
                if j not in t:
                    t[j]=dict()
                t=t[j]
            t['*']=dict()
    def query(self, letter: str) -> bool:
        self.string+=letter
        self.l+=1
        trie=self.trie
        for i in self.string[::-1]:
            if i in trie:
                trie=trie[i]
                if '*' in trie:
                    return True
            else:
                return False
        return False
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.dic = {}
        for word in words:
            if word[-1] not in self.dic:
                self.dic[word[-1]] = [word[:-1]]
            else:
                self.dic[word[-1]].append(word[:-1])
        
        self.string = \"\"

    def query(self, letter: str) -> bool:
        self.string += letter
        if letter in self.dic:
            for word in self.dic[letter]:
                length = len(word) + 1
                complete_word = word + letter
                if len(self.string) >= length and \\
                complete_word == self.string[len(self.string)-length:]:
                    return True
            return False
        else:
            return False
            
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.max_len = 0
        self.dequeue = collections.deque()
        self.suffix_dict = dict()

        for w in set(words):
            self.max_len = max(self.max_len, len(w))
            for i in reversed(range(len(w))):
                suffix = \"\".join(reversed(w[i:]))
                if suffix not in self.suffix_dict:
                    self.suffix_dict[suffix] = False
                if i == 0:
                    self.suffix_dict[suffix] = True

        #print (self.suffix_dict)

    def query(self, letter: str) -> bool:
        if len(self.dequeue) >= self.max_len:
            self.dequeue.popleft()
        self.dequeue.append(letter)

        #print(letter, self.dequeue)

        reversed_word = ''
        for i in reversed(range(len(self.dequeue))):
            c = self.dequeue[i]
            reversed_word = reversed_word + c

            #print(reversed_word)
            if reversed_word in self.suffix_dict:
                if self.suffix_dict[reversed_word]:
                    return True
            else:
                return False

        return False

class StreamChecker:
    
    openDicts = []
    cache = {}
    words = []
    acc = \"\"
    
    def __init__(self, words: List[str]):
        self.t = {}
        self.acc = \"\"
        for w in words:
            d = self.t
            for c in w[::-1]:
                d[c] = d.get(c, {})
                d = d[c]
            d['end'] = True    
        self.openDicts = [self.t]
        self.words = words
        # print(self.t)
        
    def query(self, letter: str) -> bool:
        self.acc += letter
        d = self.t
        for c in self.acc[::-1]:
            if 'end' in d:
                return True
            elif c in d:
                d = d[c]
            else:
                return False
        return 'end' in d    
            
        
        
        
#         def check(a) -> bool:
#             d = self.t
#             for i, c in enumerate(a[::-1]):
#                 if c in d:
#                     d = d[c]
#                 else:
#                     return False
#             self.cache[a] = d
#             return 'end' in d    
        
#         for i in range(len(self.acc)):
#             if check(tuple(self.acc[i:])):
#                 return True
        
#         return False
        
        
#         print('=== ', letter)
#         toDel = []
#         toAppend = []
#         foundEnd = False
#         for i, d in enumerate(self.openDicts):
#             if letter in d:
#                 print('found', letter)
#                 toAppend.append(d[letter])
#                 print(toAppend)
#                 if 'end' in d[letter]:
#                     foundEnd = True
#             else:
#                 toDel.append(i)
        
#         toDel.sort(reverse=True)
#         for i in toDel:
#             if self.openDicts[i] != self.t:
#                 del self.openDicts[i]
#                 print('del', i)
#         for a in toAppend:
#             self.openDicts.append(a)
        
#         print('after del', self.openDicts)
#         print('>>=== ', letter)
#         return foundEnd
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.words=set(words)
        self.maxx = len(max(self.words,key=len))
        self.tails = set()
        for word in self.words:
            self.tails.add(word[-1])
        self.qs = ''
    

    def query(self, letter: str) -> bool:
        self.qs +=letter
        if len(self.qs)>self.maxx:
            self.qs = self.qs[1:]
        if letter not in self.tails:
            return False
        N = len(self.qs)
        return any((self.qs[i:N] in self.words for i in range(N)))
        # return letter in self.words


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            node = self.trie
            for c in word[::-1]:
                if c not in node:
                    node[c] = {}
                node = node[c]
            node['$'] = True
        self.queries = ''
        self.W = max(list(map(len, words)))

    def query(self, letter: str) -> bool:
        ret = False
        self.queries += letter
        node = self.trie
        for c in self.queries[::-1][:self.W]:
            if c in node:
                node = node[c]
                if '$' in node:
                    return True
            else:
                return False
        return False
        
            
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from typing import List


class StreamChecker:

    def __init__(self, words: List[str]):
        self.wordsSet = Trie(words)
        self.letters = \"\"

    def query(self, letter: str) -> bool:
        self.letters += letter
        tmpLetterSequence = \"\"
        for i in range(len(self.letters)-1,-1,-1):
            tmpLetterSequence += self.letters[i]
            if not self.wordsSet.isPrefix(tmpLetterSequence):
                return False
            if self.wordsSet.hasWord(tmpLetterSequence):
                return True
        return False


class Node:
    def __init__(self):
        self.children = [None] * 26
        self.end = False


class Trie:
    def __init__(self, words):
        self.root = Node()
        for word in words:
            tmpRoot = self.root
            for j in range(len(word) -1 , -1, -1):
                letter = word[j]
                if tmpRoot.children[ord(letter)-ord('a')] is None:
                    tmpRoot.children[ord(letter)-ord('a')] = Node()
                tmpRoot = tmpRoot.children[ord(letter)-ord('a')]
            tmpRoot.end = True

    def isPrefix(self, word):
        tmpRoot = self.root
        for letter in word:
            if tmpRoot.children[ord(letter) - ord('a')] is None:
                return False
            tmpRoot = tmpRoot.children[ord(letter) - ord('a')]
        return True

    def hasWord(self, word):
        tmpRoot = self.root
        for letter in word:
            if tmpRoot.children[ord(letter) - ord('a')] is None:
                return False
            tmpRoot = tmpRoot.children[ord(letter) - ord('a')]
        if tmpRoot.end:
            return True
        return False

from collections import deque, defaultdict
class StreamChecker:

    def __init__(self, words: List[str]):
        self.words = words
        self.stream = deque(maxlen=2000)
        
        # organize based on last letter
        self.words_dict = defaultdict(list)
        for word in self.words:
            self.words_dict[word[-1]].append(word)

    def query(self, letter: str) -> bool:
        
        self.stream.append(letter)
        
        # for word in self.words:
        for word in self.words_dict[letter]:
            if len(word) <= len(self.stream):
                for i in range(len(word)):
                    if word[-(i+1)] != self.stream[-(i+1)]:
                        break
                else:
                    return True
                # if word == ''.join(self.stream[-len(word):]):
                #     return True
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TreeNode:
    def __init__(self):
        self.children = dict()
        self.isWord = False 
    
    
class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = TreeNode()
        self.sofar = ''
        for word in words:
            self.add(word)
    
    def add(self, word):
        node = self.root
        for w in word[::-1]:
            if w not in node.children:
                node.children[w] = TreeNode()
            node = node.children[w]
        node.isWord = True
                
        
        
        
    def query(self, letter: str) -> bool:
        self.sofar += letter
        node = self.root
        for c in self.sofar[::-1]:
            if c in node.children:
                node = node.children[c]
                if node.isWord:
                    return True
            else:
                return False
        return node.isWord
            
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Node(object):
    
    def __init__(self):
        self.children = {}
        self.end = False
        
    def add(self, word):
        cur = self
        for c in word:
            if c not in cur.children:
                cur.children[c] = Node()
            cur = cur.children[c]
        cur.end = True

class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = Node()
        for word in words:
            self.root.add(word[::-1])
        self.s = []
        self.cur = self.root
            
    def query(self, letter: str) -> bool:
        self.s.append(letter)
        i = len(self.s) - 1
        cur = self.root
        while i >= 0:
            c = self.s[i]
            if c not in cur.children:
                return False
            cur = cur.children[c]
            if cur.end:
                return True
            i -= 1
        return False
    
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        
        self.trie = {}
        self.pointers = []
        
        for word in words:
            curr = self.trie
            for char in word + '0':
                if char not in curr:
                    curr[char] = {}
                curr = curr[char]

    def query(self, letter: str) -> bool:
        
        new_pointers = []
        hasFound = False
        
        for pointer in self.pointers:
            if letter in pointer:
                new_pointers.append(pointer[letter])
        
        if letter in self.trie:
            new_pointers.append(self.trie[letter])
        
        self.pointers = new_pointers
        
        for pointer in self.pointers:
            if '0' in pointer:
                return True
        
        return False


class Node:
    def __init__(self):
        self.children = {}
        self.stop = False
        
class Trie:
    def __init__(self):
        self.word = Node()
    
    def insert(self, word):
        word = word[::-1]
        curr = self.word
        for l in word:
            node = curr.children.get(l, Node())
            curr.children[l] = node
            curr = node
        curr.stop = True
        
#     def startsWith(self, letter):
#         curr = self.word
        
#         for l in letter:
#             node = curr.children.get(l, None)
#             if not node:
#                 return False
#             curr = node
#         return True
    
    def search(self, word):
        curr = self.word
        
        for l in word:
            node = curr.children.get(l, None)
            
            if not node:
                return False
            elif node.stop:
                return True
            curr = node
        return curr.stop
    

class StreamChecker:

    def __init__(self, words: List[str]):
        self.t = Trie()
        for word in words:
            self.t.insert(word)
        self.pointer = ''

    def query(self, letter: str) -> bool:
        self.pointer += letter

        return self.t.search(self.pointer[::-1])
        

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie = dict()
        for word in words:
            node = self.trie
            for c in word:
                if c not in node:
                    node[c] = dict()
                node = node[c]
            node['.'] = '.'

        self.curs = []

    def query(self, letter: str) -> bool:
        trie, curs = self.trie, self.curs
        
        ans = False
        
        new_curs = []
        for cur in curs:
            if letter in cur:
                new_cur = cur[letter]
                ans = ans or '.' in new_cur
                new_curs.append(new_cur)
                
        if letter in trie:
            new_cur = trie[letter]
            ans = ans or '.' in new_cur
            new_curs.append(new_cur)
        
        self.curs = new_curs

        return ans

#
class TrieNode():
    def __init__(self):
        self.children = {}
        self.isEnd = False

class Trie(): 
    def __init__(self):
        self.root = TrieNode()
    
    def insert(self, word): 
        node = self.root 
        for char in word: 
            if char not in node.children:
                node.children[char] = TrieNode()
            node = node.children[char]
        node.isEnd = True

class StreamChecker:
    def __init__(self, words: List[str]):
        self.currquery = \"\"
        self.trie = Trie()
        for word in words: 
            self.trie.insert(word[::-1])
    
    def query(self, letter: str) -> bool:
        self.currquery += letter
        node = self.trie.root
        for i in self.currquery[::-1]: 
            if i not in node.children: 
                return False
            else: 
                node = node.children[i]
                if node.isEnd:
                    return True
                
                
    


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            curr = self.trie
            for char in word:
                if char not in curr:
                    curr[char] = {}
                curr = curr[char]
            curr[\"#\"] = True
        self.pointers = deque()

    def query(self, letter: str) -> bool:
        tmp = deque()
        self.pointers.append(self.trie)
        for p in self.pointers:
            if letter in p:
                tmp.append(p[letter])
        self.pointers = tmp
        for p in self.pointers:
            if \"#\" in p:
                return True
        return False
            
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

from collections import deque

class TrieNode(object):
    def __init__(self):
        self.children = {}
        self.nextFail = None
        self.suffixMatches = None

    def add(self, word, index=0):
        #print(word)
        if len(word) == index:
            self.boundary = True
            self.suffixMatches = [word]
            return
        c = word[index]
        if self.children.get(c, None) is None:
            self.children[c] = TrieNode()
        self.children[c].add(word, index + 1)
    def __str__(self):
        return self.__str2()

    def __str2(self, indent=0):
        space = \"  \"*indent
        return \"{}TrieNode(h={}, B={}, nf={},\
{}\".format(
            space,
            hash(self), self.suffixMatches, hash(self.nextFail) if self.nextFail else \"None\", \"\".join(space + k + \": \" + v.__str2(indent+1) + \"\
\" for k, v in self.children.items()),
            space
        ) + space + \")\"


class AhoTrie(object):
    def __init__(self, words):
        self.root = TrieNode()
        for word in words:
            self.root.add(word)
        self.__oho()

    def __oho(self):
        q = deque()
        for c, node in self.root.children.items():
            node.nextFail = self.root
            q.append(node)
        while len(q) > 0:
            node = q.popleft()
            
            for c, child in node.children.items():
                nextFail = node.nextFail
                while not nextFail.children.get(c) and nextFail is not self.root:
                    nextFail = nextFail.nextFail
                if not nextFail.children.get(c):
                    child.nextFail = nextFail
                else:
                    child.nextFail = nextFail.children.get(c)

                q.append(child)
                #child.nextFail = node.nextFail.children.get(c, node.nextFail)
                if child.suffixMatches:
                    nextFail = child.nextFail
                    while nextFail is not self.root and not nextFail.suffixMatches:
                        nextFail = nextFail.nextFail
                    if nextFail is not self.root:
                        child.suffixMatches.extend(nextFail.suffixMatches)





class StreamChecker:

    def __init__(self, words: List[str]):
        print(words)
        self.trie = AhoTrie(words) 
        self.root = self.trie.root
        self.cur = self.root
        #print(self.root)
        

    def query(self, letter: str) -> bool:
        
        
        while not self.cur.children.get(letter) and self.cur is not self.root:
            self.cur = self.cur.nextFail
        #print(hash(self.cur))
        if self.cur.children.get(letter):
            self.cur = self.cur.children[letter]
            temp = self.cur
            while temp is not self.root:
                if temp.suffixMatches:
                    return True
                temp = temp.nextFail
        return False
            
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            cur = self.trie
            for l in word:
                if l not in cur:
                    cur[l] = {}
                cur = cur[l]
            cur[\"#\"]=True
        self.stream=deque()
        

    def query(self, letter: str) -> bool:
        temp = deque()
        self.stream.append(self.trie)
        for p in self.stream:
            if letter in p:
                temp.append(p[letter])
        self.stream = temp
        
        for p in self.stream:
            if \"#\" in p:
                return True
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            cur = self.trie #root
            for char in word:
                if char not in cur:
                    cur[char] = {}
                cur = cur[char]
            cur['#'] = True
        self.stream = deque()

    def query(self, letter: str) -> bool:
        temp = deque()
        self.stream.append(self.trie)
        for p in self.stream:
            if letter in p:
                temp.append(p[letter])     
        self.stream = temp
        for p in self.stream:
            if '#' in p:
                return True
        return False
                


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.stream = deque([])
        
        for word in set(words):
            node = self.trie
            for char in word[::-1]:
                if not char in node:
                    node[char] = {}
                node = node[char]
            node['$'] = word
        print((self.trie))
        

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        
        node = self.trie
        for char in self.stream:
            if '$' in node:
                return True
            elif char not in node:
                return False
            node = node[char]
        return '$' in node


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import defaultdict

class TrieNode:
    
    def __init__(self):
        
        self.dict = defaultdict(TrieNode)
        self.is_word = False


class StreamChecker:

    def __init__(self, words: List[str]):
        '''
        Build a trie for each word in reversed order
        '''
\t\t
        # for user query record, init as empty string
        self.prefix = ''
        
        # for root node of trie, init as empty Trie
        self.trie = TrieNode()
        
        for word in words:
            
            cur_node = self.trie
            
\t\t\t# make word in reverse order
            word = word[::-1]
            
            for char in word:                
                cur_node = cur_node.dict[ char ]
            
\t\t\t# mark this trie path as a valid word
            cur_node.is_word = True
            
            
            
    def query(self, letter: str) -> bool:
        '''
        Search user input in trie with reversed order
        '''
\t\t
        self.prefix += letter
        
        cur_node = self.trie
        for char in reversed(self.prefix):
            
            if char not in cur_node.dict:
                # current char not in Trie, impossible to match words
                break
            
            cur_node = cur_node.dict[char]
        
            if cur_node.is_word:
                # user input match a word in Trie
                return True
        
        # No match
        return False


class StreamChecker:

    def __init__(self, words: List[str]):
        self.max_len = 0
        self.dequeue = collections.deque()
        self.suffix_dict = dict()

        for w in set(words):
            self.max_len = max(self.max_len, len(w))
            for i in reversed(range(len(w))):
                suffix = \"\".join(reversed(w[i:]))
                if suffix not in self.suffix_dict:
                    self.suffix_dict[suffix] = False
                if i == 0:
                    self.suffix_dict[suffix] = True

    def query(self, letter: str) -> bool:
        if len(self.dequeue) >= self.max_len:
            self.dequeue.popleft()
        self.dequeue.append(letter)

        reversed_word = ''
        for i in reversed(range(len(self.dequeue))):
            c = self.dequeue[i]
            reversed_word = reversed_word + c

            if reversed_word in self.suffix_dict:
                if self.suffix_dict[reversed_word]:
                    return True
            else:
                return False

        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

IS_CHAR = \".\"

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            node = self.trie
            for c in word:
                if c not in node:
                    node[c] = {}
                node = node[c]
            node[IS_CHAR] = word

        self.active_nodes = []

    def query(self, letter: str) -> bool:
        self.active_nodes = [node[letter] for node in self.active_nodes + [self.trie,] if letter in node]
        return any(IS_CHAR in node for node in self.active_nodes)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            cur = self.trie
            for l in word:
                if l not in cur:
                    cur[l] = {}
                cur = cur[l]
            cur[\"#\"] = True
        self.stream = deque()

    def query(self, letter: str) -> bool:
        temp = deque()
        self.stream.append(self.trie)
        for p in self.stream:
            if letter in p:
                temp.append(p[letter])
        self.stream = temp
        for p in self.stream:
            if \"#\" in p: return True
        return False

class StreamChecker:
    def __init__(self, words):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in words: reduce(dict.__getitem__, w, self.trie)['#'] = True
        self.waiting = []

    def query(self, letter):
        self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any(\"#\" in node for node in self.waiting)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            p = self.trie
            for c in word:
                if c not in p: p[c] = {}
                p = p[c]
            
            p['$'] = True
        
        self.pointers = []
        
    def query(self, letter: str) -> bool:
        self.pointers.append(self.trie)
        
        new_pointers = []
        found = False
        for pointer in self.pointers:
            if letter in pointer:
                new_pointers.append(pointer[letter])
                if '$' in pointer[letter]: found = True
        self.pointers = new_pointers
        return found
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            cur = self.trie
            for l in word:
                if l not in cur:
                    cur[l] = {}
                cur = cur[l]
            cur[\"#\"] = True
        self.stream = deque()

    def query(self, letter: str) -> bool:
        temp = deque()
        self.stream.append(self.trie)
        for p in self.stream:
            if letter in p:
                temp.append(p[letter])
        self.stream = temp
        for p in self.stream:
            if \"#\" in p: return True
        return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.nodes = []
        for word in words:
            node = self.trie
            for char in word:
                if char not in node:
                    node[char] = {}
                node = node[char]
            node['end'] = True

    def query(self, letter: str) -> bool:
        self.nodes.append(self.trie)
        temp = False
        new_nodes = []
        
        for node in self.nodes:
            if letter in node:
                node = node[letter]
                if 'end' in node:
                    temp = True
                new_nodes.append(node)
        self.nodes = new_nodes
        return temp


class TrieNode():
    def __init__(self):
        self.children = {}
        self.isEnd = False

class Trie():
    def __init__(self):
        self.root = TrieNode()
    
    def insert(self, word):
        node = self.root
        for char in word:
            if char not in node.children:
                node.children[char] = TrieNode()
            node = node.children[char]
        node.isEnd = True

class StreamChecker:
    def __init__(self, words: List[str]):
        self.letters = collections.deque()
        self.trie = Trie()
        self.maxlen = 0
        for w in words:
            self.trie.insert(w[::-1])
            self.maxlen = max(self.maxlen, len(w))
        
    def query(self, letter: str) -> bool:
        self.letters.append(letter)
        if len(self.letters) > self.maxlen:
            self.letters.popleft()
        i = len(self.letters) - 1
        node = self.trie.root
        while i >= 0:
            if node.isEnd:
                return True
            if self.letters[i] not in node.children:
                return False
            node = node.children[self.letters[i]]
            i -= 1
        return node.isEnd











# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in words: reduce(dict.__getitem__, w, self.trie)['#'] = True
        self.waiting = []

    def query(self, letter: str) -> bool:
        self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any(\"#\" in node for node in self.waiting)    


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

# Solution 3: Trie (Accepted)
# Only a part of suffixes can be the prefix of a word,
# waiting for characters coming to form a complete word.
# Instead of checking all W suffixes in each query,
# we can just save those possible waiting prefixes in a waiting list.

# Explanation
# Initialization:

# Construct a trie
# declare a nonlocal waiting list.
# Query:

# for each node in the waiting list,
# check if there is child node for the new character.
# If so, add it to the new waiting list.
# return true if any node in the waitinglist is the end of a word.
# Time Complexity:
# waiting.size <= W, where W is the maximum length of words.
# So that O(query) = O(waiting.size) = O(W)
# We will make Q queries, the overall time complexity is O(QW)

# Note that it has same complexity in the worst case as solution 2 (like \"aaaaaaaa\" for words and query),
# In general cases, it saves time checking all suffixes, and also the set search in a big set.

# Space Complexity:

# waiting.size <= W, where W is the maximum length of words.
# waiting list will take O(W)

# Assume we have initially N words, at most N leaves in the trie.
# The size of trie is O(NW).

# Python:
# Time: 6000+ms

class StreamChecker(object):

    def __init__(self, words):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in words: reduce(dict.__getitem__, w, self.trie)['#'] = True
        self.waiting = []

    def query(self, letter):
        self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any(\"#\" in node for node in self.waiting)
    
    

#     class StreamChecker(object):

#     def __init__(self, words):
#         \"\"\"
#         :type words: List[str]
#         \"\"\"      
#         self.waitlist = []
#         self.trie = dict()
#         for word in words:
#             # create a temporary dict based off our root dict object
#             temp_dict = self.trie
#             for letter in word:
#                 # update our temporary dict and add our current letter and a sub-dictionary
#                 # if key is not in dict, setdefault() will add {key:{}} and return default value {}
#                 # otherwise it will directly return the existing value of key
#                 temp_dict = temp_dict.setdefault(letter, dict())
#             # If our word is finished, add {'#': '#'} at the stopping node
#             temp_dict['#'] = '#'

#     def query(self, letter):
#         \"\"\"
#         :type letter: str
#         :rtype: bool
#         \"\"\"
#         waitlist = []
#         # if letter can be the prefix of word
#         if letter in self.trie:
#             waitlist.append(self.trie[letter])
#         # for each possible prefix, append letter if the new substr still can be a prefix
#         for item in self.waitlist:
#             if letter in item:
#                 waitlist.append(item[letter])
                
#         self.waitlist = waitlist
#         return any('#' in item for item in self.waitlist)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.nodes = []
        
        for word in words:
            node = self.trie
            for c in word:
                if c not in node:
                    node[c] = {}
                node = node[c]
            node['end'] = True

    def query(self, letter: str) -> bool:
        self.nodes.append(self.trie)
        temp = False
        new_nodes = []
        
        for node in self.nodes:
            if letter in node:
                node = node[letter]
                if 'end' in node:
                    temp = True
                new_nodes.append(node)
                
        self.nodes = new_nodes
        
        return temp


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
  def __init__(self, words: List[str]):
    self.active = []
    self.root = {}

    for word in words:
      current = self.root
      for c in word:
        if c not in current:
          current[c] = {}
        current = current[c]
      current['word'] = True

  def query(self, letter: str) -> bool:
    self.active = [node[letter] for node in self.active if letter in node]
    if letter in self.root:
      self.active.append(self.root[letter])
    return any('word' in node for node in self.active)
    


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in words: reduce(dict.__getitem__, w, self.trie)['#'] = True
        self.waiting = []


        

    def query(self, letter: str) -> bool:
        self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any(\"#\" in node for node in self.waiting)
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.queryStr = \"\"
        self.trie = dict()
        for word in words:
            currNode = self.trie
            for letter in word[::-1]:
                if letter not in currNode:
                    currNode[letter] = {}
                currNode = currNode[letter]
            currNode['#'] = {}             

    def query(self, letter: str) -> bool:
        self.queryStr += letter
        currNode = self.trie
        for l in self.queryStr[::-1]:
            if l not in currNode:
                return False
            
            currNode = currNode[l]
                
            if '#' in currNode:
                return True

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in words: reduce(dict.__getitem__, w, self.trie)['#'] = True
        self.waiting_list = []

    def query(self, letter: str) -> bool:
        self.waiting_list = [node[letter] for node in self.waiting_list + [self.trie] if letter in node]
        return any(\"#\" in node for node in self.waiting_list)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.words=[word[::-1] for word in words]
        self.string=''
        self.l=0
        self.createTrie()
    def createTrie(self):
        for i in self.words:
            t=self.trie
            for j in i:
                if j not in t:
                    t[j]=dict()
                t=t[j]
            t['*']=dict()
    def searchTrie(self, word):
        trie=self.trie
        for i in word:
            if i in trie:
                trie=trie[i]
            else:
                return False
        return '*' in trie
    def query(self, letter: str) -> bool:
        self.string+=letter
        self.l+=1
        trie=self.trie
        for i in self.string[::-1]:
            if i in trie:
                trie=trie[i]
                if '*' in trie:
                    return True
            else:
                return False
        return False
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
  def __init__(self):
    self.children = collections.defaultdict(TrieNode)
    self.end = False

class ReverseTrie:
    
  def __init__(self, words):
    self.root = TrieNode()
    
    for word in words:
      self.add_reverse_word(word)
      
  def add_reverse_word(self, word):
    curr_node = self.root
    
    for idx in range(len(word) - 1, -1, -1):
      char = word[idx]
      curr_node = curr_node.children[char]
      
    curr_node.end = True
    
  def reverse_word_exists(self, reverse_letters):
    
    curr_trie_node = self.root
    for char in reverse_letters:
      if char in curr_trie_node.children:
        curr_trie_node = curr_trie_node.children[char]
        if curr_trie_node.end:
          return True
      else:
        return False
      
      
    return False
      
      
class StreamChecker:

    def __init__(self, words: List[str]):
        self.last_n_queries = collections.deque([])
        self.trie_reverse_words = ReverseTrie(words)
        self.max_word_length = 2000

    def query(self, letter: str) -> bool:
      
      self.last_n_queries.appendleft(letter)
      
      if len(self.last_n_queries) > self.max_word_length:
        self.last_n_queries.pop()
        
      return self.trie_reverse_words.reverse_word_exists(self.last_n_queries)

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

#cd, f, kl


class StreamChecker:

    def __init__(self, words: List[str]):
        
        self.trie = {}
        for word in words:
            cur = self.trie
            for l in word:
                if l not in cur:
                    cur[l] = {}
                cur = cur[l]
            cur['#'] = True
        self.stream = deque()
                

    def query(self, letter: str) -> bool:
        
        temp = deque()
        self.stream.append(self.trie)
        for p in self.stream:
            if letter in p:
                temp.append(p[letter])
        self.stream = temp
        for p in self.stream:
            if '#' in p: return True
        return False
                


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = {}
        
        for word in words:
            node = self.root
            for char in word:
                if char not in node:
                    node[char] = {}
                node = node[char]
            node['#'] = 1
        
        # Node pointer of current valid candidates for matches
        self.candidates = []
        
    def query(self, letter: str) -> bool:
        
        found = False
        
        new_candidates = []
        self.candidates.append(self.root)
        for node in self.candidates:
            if letter in node:
                node = node[letter]
                new_candidates.append(node)
                if '#' in node:
                    found = True

        self.candidates = new_candidates
        
        return found

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.nodes = []
        for word in words:
            node = self.trie
            for char in word:
                if char not in node:
                    node[char] = {}
                node=node[char]
            node['end'] = True
            

    def query(self, letter: str) -> bool:
        self.nodes.append(self.trie)
        temp = False
        new_nodes=[]
        
        for node in self.nodes:
            if letter in node:
                node=node[letter]
                if 'end' in node:
                    temp = True
                new_nodes.append(node)
        self.nodes=new_nodes
        return temp
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker():
    def __init__(self, words: List[str]):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in words: reduce(dict.__getitem__, w, self.trie)['#'] = True
        self.waiting = []

    def query(self, letter: str) -> bool:
        self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any(\"#\" in node for node in self.waiting)

class StreamChecker:
    def __init__(self, words: List[str]):
        Trie = lambda: collections.defaultdict(Trie)
        self.trie = Trie()
        for word in words: reduce(dict.__getitem__, word, self.trie)['eow'] = True
        self.trie_list = []

    def query(self, letter: str) -> bool:
        self.trie_list = [node[letter] for node in self.trie_list + [self.trie] if letter in node]
        return any('eow' in trie for trie in self.trie_list)

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


import json

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.ptrs = []
        
        for word in words:
            curr = self.trie
            for c in word:
                if c not in curr:
                    curr[c] = {}
                curr = curr[c]
            curr[\".\"] = {}
    
    def query(self, letter: str) -> bool:
        res = False
        newPtrs = []
        
        if letter in self.trie:
            curr = self.trie[letter]
            newPtrs.append(curr)
            if \".\" in curr:
                res = True
        
        for ptr in self.ptrs:
            if letter in ptr:
                curr = ptr[letter]
                newPtrs.append(curr)
                if \".\" in curr:
                    res = True
        self.ptrs = newPtrs
        
        return res


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in words: reduce(dict.__getitem__, w, self.trie)['#'] = True
        self.waiting = []

    def query(self, letter):
        self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any(\"#\" in node for node in self.waiting)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.nodes = []
        for word in words:
            node = self.trie
            for char in word:
                if char not in node:
                    node[char] = {}
                node = node[char]
            node['end'] = True

    def query(self, letter: str) -> bool:
        self.nodes.append(self.trie)
        temp = False
        new_nodes = []
        
        for node in self.nodes:
            if letter in node:
                node = node[letter]
                if 'end' in node:
                    temp = True
                new_nodes.append(node)
        self.nodes = new_nodes
        return temp

class StreamChecker:

    def __init__(self, words: List[str]):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in words:
            reduce(dict.__getitem__, w, self.trie)['#'] = True
        self.waiting = []

    def query(self, letter: str) -> bool:
        self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any('#' in node for node in self.waiting)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


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

class StreamChecker:

    def __init__(self, words):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in words: reduce(dict.__getitem__, w, self.trie)['#'] = True
        self.waiting = []

    def query(self, letter):
        self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any(\"#\" in node for node in self.waiting)

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

from collections import defaultdict
from functools import reduce

class StreamChecker:

    def __init__(self, words: List[str]):
        # O(N x M)

        # self.s = \"\"
        # self.dic = defaultdict(set)
        # for w in words:
        #     self.dic[w[-1]].add(w)

        Trie = lambda: defaultdict(Trie)
        self.trie = Trie()
        for word in words:
            reduce(dict.__getitem__, word, self.trie)['#'] = True
        self.waiting = []
        

    def query(self, letter: str) -> bool:
        # O(M) where M is a max word length.

        # self.s += letter
        # return any(self.s.endswith(w) for w in self.dic[letter])


        self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any('#' in node for node in self.waiting)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


import functools

class StreamChecker:

    def __init__(self, words: List[str]):
        T=lambda: collections.defaultdict(T)
        self.trie=T()
        for word in words:
            functools.reduce(dict.__getitem__,word,self.trie)[\"#\"]=True
        self.waiting=[]
        

    def query(self, letter: str) -> bool:
        self.waiting=[node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any(\"#\" in node for node in self.waiting)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

from functools import reduce
class StreamChecker(object):

    def __init__(self, words):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in words: reduce(dict.__getitem__, w, self.trie)['#'] = True
        self.waiting = []

    def query(self, letter):
        self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any(\"#\" in node for node in self.waiting)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            cur = self.trie #root
            for char in word:
                if char not in cur:
                    cur[char] = {}
                cur = cur[char]
            cur['#'] = True
        self.stream = deque()
        print((self.trie))

    def query(self, letter: str) -> bool:
        temp = deque()
        self.stream.append(self.trie)
        for p in self.stream:
            if letter in p:
                temp.append(p[letter])     
        self.stream = temp
        for p in self.stream:
            if '#' in p:
                return True
        return False
                


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = {}
        self.nodes = []
        for word in words:
            cur = self.root
            for char in word:
                if char not in cur:
                    cur[char] = {}
                cur = cur[char]
            cur['*'] = True
        
                

    def query(self, letter: str) -> bool: 
        self.nodes.append(self.root)
        newNodes = []
        ans = False
        for node in self.nodes:
            if letter in node:
                node = node[letter]
                if '*' in node:
                    ans = True
                newNodes.append(node)
        self.nodes = newNodes
        return ans
                
                


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


import collections
class StreamChecker(object):

    def __init__(self, words):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in words: reduce(dict.__getitem__, w, self.trie)['#'] = True
        self.waiting = []

    def query(self, letter):
        self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any(\"#\" in node for node in self.waiting)
        \"\"\"
        :type letter: str
        :rtype: bool
        \"\"\"
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

from itertools import chain

class StreamChecker:
    prefixes = []

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            d = self.trie
            for letter in word:
                if letter not in d:
                    d[letter] = {}
                d = d[letter]
            d['end'] = True

    def query(self, letter: str) -> bool:
        self.prefixes = [node[letter] for node in chain([self.trie], self.prefixes) if letter in node]
        return any('end' in node for node in self.prefixes)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        trie = {}

        
        for w in words:
            node = trie
            for c in w:
                if c not in node:
                    node[c] = {}
                    node = node[c]
                    node['fail'] = trie
                else:
                    node = node[c]
                
            node['end'] = True
        
        que = [trie[x] for x in trie]
        for node in que:
            for x in node:
                if x not in ('end', 'fail'):
                    p = node['fail']
                    while p != trie and x not in p:
                        p = p['fail']
                    if x in p:
                        node[x]['fail'] = p[x]
                        if 'end' in p[x]:
                            node[x]['end'] = True
                    que.append(node[x])
        self.trie = trie
        self.node = trie

    def query(self, x: str) -> bool:
        trie = self.trie
        node = self.node
        while node != trie and x not in node:
            node = node['fail']
        if x in node:
            node = node[x]
        self.node = node
        return 'end' in node
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.nodes = []
        for word in words:
            node = self.trie
            for char in word:
                if char not in node:
                    node[char] = {}
                node = node[char]
            node['end'] = True

    def query(self, letter: str) -> bool:
        self.nodes.append(self.trie)
        temp = False
        new_nodes = []
        
        for node in self.nodes:
            if letter in node:
                node = node[letter]
                if 'end' in node:
                    temp = True
                new_nodes.append(node)
        self.nodes = new_nodes
        return temp

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        Trie = lambda: collections.defaultdict(Trie)
        self.trie = Trie()

        for word in words:
            functools.reduce(dict.__getitem__, word, self.trie)['#'] = True

        self.heads = []

    def query(self, letter: str) -> bool:
        self.heads = [h[letter] for h in self.heads if letter in h]
        if letter in self.trie:
            self.heads.append(self.trie[letter])
        return any('#' in h for h in self.heads)

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.hist = \"\"
        
        for word in words:
            t = self.trie
            for w in word[::-1]:
                if w not in t:
                    t[w] = {}
                t = t[w]
            t['$'] = '$'

    def query(self, letter: str) -> bool:
        self.hist += letter
        ctrie = self.trie
        for l in self.hist[::-1]:
            if l not in ctrie:
                return False
            ctrie = ctrie[l]
            
            if '$' in ctrie:
                return True
        return False
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        
        self.d = {}
        
        for word in words:
            ptr = self.d
            for c in word:
                if c not in ptr:
                    ptr[c] = {}
                ptr = ptr[c]
            ptr[''] = True 
                
        self.curr = self.d
        self.q = []
        

    def query(self, letter: str) -> bool:

        self.q.append(self.d)
        
        # print(letter, len(self.q))
        temp = []
        flag = False
        for ptr in self.q:            
            if letter in ptr:
                ptr = ptr[letter]
                temp.append(ptr)
                if '' in ptr:
                    flag = True
        
        self.q = temp
        
        return flag
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker(object):

    def __init__(self, words):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in words: reduce(dict.__getitem__, w, self.trie)['#'] = True
        self.waiting = []

    def query(self, letter):
        self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any(\"#\" in node for node in self.waiting)

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = {}
        for word in words:
            curnode = self.root
            for ch in word:
                if ch not in curnode:
                    curnode[ch] = {}
                curnode = curnode[ch]
            curnode['is_end'] = True
        self.leads = [self.root] # the pointers to the threads we follow right now

    def query(self, letter: str) -> bool:
        next_leads = [self.root]
        found_word = False
        for lead in self.leads:
            if letter in lead:
                new_lead = lead[letter]
                next_leads.append(new_lead)
                if 'is_end' in new_lead:
                    found_word = True
        self.leads = next_leads
        return found_word
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__ (self):
        self.children: Dict[str, TrieNode] = {}
    def __str__ (self):
        l = \"\"
        for s in self.children:
            l = l+s+\"[\"
            if self.children[s]:
                l = l+str(self.children[s])
            l = l+\"]\"
        return(l)


class ZStreamChecker:    
    
    def __init__(self, words: List[str]):
        self.root = TrieNode()
        for w in words:
            p = self.root
            for l in w:
                if l not in p.children:
                    p.children[l] = TrieNode()
                p = p.children[l]
        self.pointers = set()
        self.pointers.add(self.root)

    def query(self, letter: str) -> bool:
        ret = False
        newset = set()
        newset.add(self.root)
        for p in self.pointers:
            if letter in p.children:
                if p.children[letter].children=={}:
                    ret = True
                else:
                    newset.add(p.children[letter])
        self.pointers = newset
        return ret
                
class StreamChecker(object):

    def __init__(self, words):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in words: reduce(dict.__getitem__, w, self.trie)['#'] = True
        self.waiting = []

    def query(self, letter):
        self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any(\"#\" in node for node in self.waiting)

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

from itertools import chain

class StreamChecker:
    prefixes = []

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            d = self.trie
            for letter in word:
                d = d.setdefault(letter, {})
            d['end'] = True

    def query(self, letter: str) -> bool:
        self.prefixes = [node[letter] for node in chain([self.trie], self.prefixes) if letter in node]
        return any('end' in node for node in self.prefixes)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.words = sorted([ww[::-1] for ww in words])
        self.entries = {}
        self.create_trie(words)
        self.nodes = []

    def create_trie(self, word_list):
        for word in word_list:
            curNode = self.entries
            for i in range(len(word)):
                cur = word[i]
                if cur not in curNode:
                    curNode[cur] = {}
                curNode = curNode[cur]
            curNode[\"#\"] = True

    def query(self, letter: str) -> bool:
        res = False
        self.nodes.append(self.entries)
        new_nodes = []
        for node in self.nodes:
            if letter in node:
                node = node[letter]
                if \"#\" in node:
                    res = True
                new_nodes.append(node)
        self.nodes = new_nodes
        return res


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self):
        self.isEnd = False
        self.children = dict()

class Trie:
    def __init__(self):
        self.root = TrieNode()
        
    def addNode(self,word):
        curNode = self.root
        for char in word:
            if char not in curNode.children:
                curNode.children[char] = TrieNode()
            curNode = curNode.children[char]
        curNode.isEnd = True
        
    def search(self,word):
        curNode = self.root
        for char in word:
            if curNode.isEnd: return True
            elif char not in curNode.children: return False
            else: curNode = curNode.children[char]
        return curNode.isEnd

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        for word in words:
            self.trie.addNode(word[::-1])
        self.curWord = ''

    def query(self, letter: str) -> bool:
        self.curWord = letter + self.curWord
        return self.trie.search(self.curWord)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        head = {}
        
        for w in words:
            current = head
            for c in w:
                if c not in current:
                    current[c] = {}
                current = current[c]
            current['X'] = None

            
        self.head = head
        self.current = [head]
        
    def query(self, letter: str) -> bool:
        new_current = [self.head]
        for e in self.current:
            if letter in e: new_current.append(e[letter])
                
        self.current = new_current
        for e in new_current:
            if 'X' in e: return True
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import defaultdict
def routing():
    return defaultdict(routing)
class StreamChecker:
    def __init__(self, words: List[str]):
        self.router = routing()
        for word in words:
            root = self.router
            for letter in word:
                root = root[letter]
            root[\"*\"] = word
        self.queries = []
    def query(self, letter: str) -> bool:
        new_queries, matches = [], []
        self.queries.append(self.router)
        for q in self.queries:
            if letter in q:
                q = q[letter]
                if '*' in q:
                    matches.append(q[\"*\"])
                    if len(q) > 1:
                        new_queries.append(q)
                else:
                    new_queries.append(q)
        self.queries = new_queries
        return bool(matches)

class StreamChecker:
    def __init__(self, words):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in words: reduce(dict.__getitem__, w, self.trie)['#'] = True
        self.waiting = []

    def query(self, letter):
        self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any(\"#\" in node for node in self.waiting)

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Node:
    def __init__(self, char, parent):
        self.children = [None for _ in range(26)]
        self.char = char
        self.parent = parent
        

class StreamChecker:

    def __init__(self, words: List[str]):
        self.map = {}
        self.root = Node(' ', None)
        self.buffer = deque()
        self.max_size = max([len(word) for word in words])
        self.add(words)
    
    def add(self, words):
        for word in words:
            curr = self.root
            for c in word:
                if not curr.children[ord(c) - ord('a')]:
                    curr.children[ord(c) - ord('a')] = Node(c, curr)
                curr = curr.children[ord(c) - ord('a')]
            if word[-1] not in self.map:
                self.map[word[-1]] = []
            self.map[word[-1]].append(curr)

    def query(self, letter: str) -> bool:
        self.buffer.append(letter)
        if len(self.buffer) > self.max_size:
            self.buffer.popleft()
        if letter not in self.map:
            return False
        for node in self.map[letter]:
            curr = node
            for i in range(len(self.buffer) - 2, -1, -1):
                if curr is not self.root and curr.parent.char == self.buffer[i]:
                    curr = curr.parent
                else:
                    break
            if curr.parent is self.root:
                return True
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    def __init__(self, words):
        self.root = {}
        self.build(words)
    
    def build(self, words):
        for word in words:
            self.add_word(word)
            
    def add_word(self, word):
        node = self.root
        for ch in word:
            if ch not in node:
                node[ch] = {}
            node = node[ch]
        node[\"$\"] = True

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie(words)
        self.prev_nodes = []

    def query(self, letter: str) -> bool:
        result = False
        new_nodes = []
        self.prev_nodes.append(self.trie.root)
        for node in self.prev_nodes:
            if letter in node:
                if \"$\" in node[letter]:
                    result = True
                new_nodes.append(node[letter])
        self.prev_nodes = new_nodes
        return result


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Node:
    def __init__(self, char, parent):
        self.children = [None for _ in range(26)]
        self.char = char
        self.parent = parent
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.map = {}
        self.root = Node(' ', None)
        self.buffer = deque()
        self.max_size = max([len(word) for word in words])
        self.add(words)
    
    def add(self, words):
        for word in words:
            curr = self.root
            for c in word:
                if not curr.children[ord(c) - ord('a')]:
                    curr.children[ord(c) - ord('a')] = Node(c, curr)
                curr = curr.children[ord(c) - ord('a')]
            if word[-1] not in self.map:
                self.map[word[-1]] = []
            self.map[word[-1]].append(curr)

    def query(self, letter: str) -> bool:
        self.buffer.append(letter)
        if len(self.buffer) > self.max_size:
            self.buffer.popleft()
        if letter not in self.map:
            return False
        for node in self.map[letter]:
            curr = node
            for i in range(len(self.buffer) - 2, -1, -1):
                if curr is not self.root and curr.parent.char == self.buffer[i]:
                    curr = curr.parent
                else:
                    break
            if curr.parent is self.root:
                return True
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    
    def __init__(self):
        self.dict = {}
        self.leaf = False
        
    def addWord(self,word):
        curTrie = self
        for ch in word:
            if ch not in curTrie.dict:
                curTrie.dict[ch] = Trie()
            curTrie = curTrie.dict[ch]
        curTrie.leaf = True
        
    def search(self,query):
        curTrie = self
        # print('query : {}'.format(query))
        for ch in query:
            if ch in curTrie.dict:
                curTrie = curTrie.dict[ch]
                if curTrie.leaf == True:
                    return True
            else:
                return False
        return False
            
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.queryStr = ''
        for word in words:
            self.trie.addWord(word[::-1])
        
    def query(self, letter: str) -> bool:
        self.queryStr += letter
        curTrie = self.trie
        return curTrie.search(self.queryStr[::-1])

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.chars=[]
        self.trie={}
        for word in words:
            curr=self.trie
            for c in reversed(word):
                if c not in curr:
                    curr[c]={}
                curr=curr[c]
            curr['#']=True
    
    def search(self):
        ind=len(self.chars)-1
        curr=self.trie
        while curr and ind>=0:
            if '#' in curr:
                return True
            c=self.chars[ind]
            if c not in curr:
                return False
            
            curr=curr[c]
            ind-=1
        return curr and '#' in curr
        

    def query(self, letter: str) -> bool:
        self.chars.append(letter)
        return self.search()


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.words = set(words)
        self.query_history = \"\"
        self.max_word_len = max(map(len, words))

    def query(self, letter: str) -> bool:
        self.query_history = self.query_history[-self.max_word_len:] + letter
        return any(self.query_history.endswith(word) for word in self.words)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:
    def __init__(self, words: List[str]):
        T = lambda: collections.defaultdict(T)  # Template class used to construct trie
        self.trie = T()
        for w in words:
            functools.reduce(dict.__getitem__, w, self.trie)['#'] = True
        self.possible_list = []

    def query(self, letter: str) -> bool:
        self.possible_list = [node[letter] for node in self.possible_list + [self.trie] if letter in node]
        return any('#' in node for node in self.possible_list)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for w in words:
            d = self.trie
            for c in w:
                if c in d:
                    d = d[c]
                else:
                    d[c] = {}
                    d = d[c]
            d['$'] = None
        self.l = []

    def query(self, letter: str) -> bool:
        self.l = [j[letter] for j in self.l if letter in j]
        if letter in self.trie:
            self.l.append(self.trie[letter])
        return any(['$' in i for i in self.l])
        
                
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker(object):
    \"\"\"
    Copy paste from Lee215 on discussions
    My code is still being built but lazy...
    Also found another good resource for backend sys design... I'm sorry...
    \"\"\"
    def __init__(self, words):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in words: reduce(dict.__getitem__, w, self.trie)['#'] = True
        self.waiting = []

    def query(self, letter):
        self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any(\"#\" in node for node in self.waiting)

class TrieNode:
    
    def __init__(self):
        self.word = False
        self.child = defaultdict(TrieNode)

class StreamChecker1:

    def __init__(self, words: List[str]):
        \"\"\"
        Took around 5 minutes for the approach...
        45 minutes for the implementation... 
        Also did some amazon and day dreaming... in the noon...
        Not sure if this will run... but very hopeful...
        \"\"\"
        self.trie = TrieNode()
        for w in words:
            itr = self.trie
            for ch in w: itr = itr.child[ch]
            itr.word = True
        self.pointers = collections.deque(self.trie.child.items())

    def query(self, letter: str) -> bool:
        found, lt_indices = False, []
        for i, pair in enumerate(self.pointers): 
            k, v = pair
            if k == letter: lt_indices.append(i)
        
        print(letter, lt_indices)
        for i in lt_indices:
            k, v = self.pointers[i]
            
            if v.word: found = True
                
            self.pointers.extend(v.child.items())
        
        cnt = 0
        for i in lt_indices: 
            del self.pointers[i - cnt]
            cnt += 1
        
        print(letter, self.pointers, found)
        return found


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.t = {}
        for word in words:
            t = self.t
            for ch in word:
                t = t.setdefault(ch, {})
            t['#'] = 'END'
                    
        self.cursors = [self.t]
        

    def query(self, letter: str) -> bool:
        
        newcursors = []
        ans = False
        
        for cur in self.cursors:
            if letter not in cur:
                continue
            cur = cur[letter]
            if '#' in cur:
                ans = True
            newcursors.append(cur)
            
        self.cursors = newcursors
        self.cursors.append(self.t)
        
        return ans


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


# class TrieNode:
#     def __init__(self):
#         self.children = [None]*26
#         self.end = False

# class StreamChecker:

#     def char_to_index(self,ch):
#         return ord(ch) - ord('a')
    
#     def insert(self,word):
#         n = len(word)    
#         ptr = self.root
#         for lvl in range(len(word)):
#             i = self.char_to_index(word[lvl])
#             if ptr and not ptr.children[i]:
#                 ptr.children[i] = TrieNode()
                
#             ptr = ptr.children[i]
            
#         ptr.end = True
        
#     def __init__(self, words: List[str]):
#         self.root = TrieNode
        
#         for word in words:
#             self.insert(word)
#         self.pe = None

#     def query(self, letter: str) -> bool:
        
#         if self.pe and self.pe.children[char_to_index(letter)]:
#             if self.pe.end:
#                 return True
#             self.pe = self.pe.children[char_to_index(letter)]
#             return False
        
#         if self.root.children[char_to_index(letter)]:
#             self.pe = self.root.children[char_to_index(letter)]
#             if self.root.end:
#                 return True
#             return False
            
        


# # Your StreamChecker object will be instantiated and called as such:
# # obj = StreamChecker(words)
# # param_1 = obj.query(letter)


class StreamChecker(object):

    def __init__(self, words):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in words: reduce(dict.__getitem__, w, self.trie)['#'] = True
        self.waiting = []

    def query(self, letter):
        self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any(\"#\" in node for node in self.waiting)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            t = self.trie
            for c in word+'\\0':
                if c not in t: t[c] = {}
                t = t[c]
        self.nodes = [self.trie]
            
    def query(self, letter: str) -> bool:
        newNodes = [self.trie]
        ret = False
        for node in self.nodes:
            if letter in node:
                newNodes.append(node[letter])  
                if '\\0' in node[letter]: ret = True
        self.nodes = newNodes
        return ret
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.waitList = []
        self.trie = {}
        for w in words:
            curr = self.trie
            for c in w:
                if c not in curr:
                    curr[c] = {}
                curr = curr[c]
            curr['#'] = {'#'}

    def query(self, letter: str) -> bool:
        newWaitList = []
        if letter in self.trie:
            newWaitList.append(self.trie[letter])
        for ele in self.waitList:
            if letter in ele:
                newWaitList.append(ele[letter])
        self.waitList = newWaitList
        for ele in self.waitList:
            if '#' in ele:
                return True
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for w in words:
            curr = self.trie
            for c in w+\"#\":
                curr = curr.setdefault(c, {})
        self.matching = []

    def query(self, letter: str) -> bool:
        if letter in self.trie:
            self.matching.append(self.trie)
        res = []
        ans = False
        for i in self.matching:
            if letter in i:
                res.append(i[letter])
                if \"#\" in i[letter]:
                    ans = True
        self.matching = res
        return ans
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode():
    def __init__(self):
        self.children = collections.defaultdict()
        self.isEnd = False

class Trie():
    def __init__(self):
        self.root = TrieNode()
    
    def insert(self, word):
        node = self.root
        for char in word:
            if char not in node.children:
                node.children[char] = TrieNode()
            node = node.children[char]
        node.isEnd = True

class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.maxlen = 0
        self.cache = []
        for w in words:
            self.trie.insert(w[::-1])
            self.maxlen = max(self.maxlen, len(w))
        
    def query(self, letter: str) -> bool:
        self.cache.append(letter)
        i = len(self.cache) - 1
        node = self.trie.root
        while i >= 0:
            if node.isEnd:
                return True
            if self.cache[i] not in node.children:
                # self.cache = self.cache[i:]
                return False
            node = node.children[self.cache[i]]
            i -= 1
        return node.isEnd
 

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.nodes = []
        for word in words:
            node = self.trie
            for char in word:
                if char not in node:
                    node[char] = {}
                node = node[char]
            node['end'] = True

    def query(self, letter: str) -> bool:
        self.nodes.append(self.trie)
        temp = False
        new_nodes = []
        
        for node in self.nodes:
            if letter in node:
                node = node[letter]
                if 'end' in node:
                    temp = True
                new_nodes.append(node)
        self.nodes = new_nodes
        return temp
        
        

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.tree = {}
        for word in words:
            ptr = self.tree
            for c in word:
                if c not in ptr:
                    ptr[c] = {}
                ptr = ptr[c]
            ptr[\"$\"] = word
        self.possible = []
        

    def query(self, letter: str) -> bool:
        # check if 
        nxt = []
        
        for p in self.possible:
            if letter in p:
                nxt.append(p[letter])
                
        if letter in self.tree:
            nxt.append(self.tree[letter])
                
        self.possible = nxt.copy()
        for p in self.possible:
            if \"$\" in p:
                return True
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Trie:
    
    def __init__(self):
        self.dict = {}
        self.leaf = False
        
    def addWord(self,word):
        newTrie = Trie()
        if word[0] in self.dict:
            newTrie = self.dict[word[0]]
        else:
            self.dict[word[0]] = newTrie
        if len(word) == 1:
            newTrie.leaf = True
        else:
            newTrie.addWord(word[1:])

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.queryStr = ''
        for word in words:
            self.trie.addWord(word[::-1])
        
    def query(self, letter: str) -> bool:
        self.queryStr += letter
        curTrie = self.trie
        #print(letter)
        for ch in self.queryStr[::-1]:
            if ch in curTrie.dict:
                curTrie = curTrie.dict[ch]
                if curTrie.leaf == True:
                    return True
            else:
                return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            t = self.trie
            for c in word:
                if c not in t:
                    t[c] = {}
                t = t[c]
            t['$'] = {}
        self.ptrs = deque()
        self.ptrs.append(self.trie)
        return

    def query(self, letter: str) -> bool:
        ret = False
        nextPtrs = deque()
        nextPtrs.append(self.trie)
        for ptr in self.ptrs:
            if letter in ptr:
                nextPtrs.append(ptr[letter])
                if '$' in ptr[letter]:
                    ret = True
        self.ptrs = nextPtrs
        return ret


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
            
    def __init__(self, words: List[str]):
        root = {}
        nodes = [root]
        for w in words:
            prev = root
            for s in w:
                if s in prev:
                    node = prev[s]
                else:
                    node = {}
                    prev[s] = node
                prev = node
            prev['None'] = None
        self.array_nodes = []
        self.root = root
        # print(self.root)
        
    def query(self, letter: str) -> bool:
        if letter in self.root:
            self.array_nodes.append(self.root)
        nodes = []
        result = False
        for node in self.array_nodes:
            if letter in node:
                nodes.append(node[letter])
                if 'None' in node[letter]:
                    result = True
        self.array_nodes = nodes
        return result
                
                
                
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        
        self.s = ''
        self.c = 0
       
        self.ld = dict()
        self.lths = set()
        
        for x in list(set(words)):
            lim = len(x)
            self.lths.add(lim)
            try:
                self.ld[lim][x[-1]].add(x)
            except:
                try:
                    self.ld[lim][x[-1]]=set()
                    self.ld[lim][x[-1]].add(x)
                except:
                    self.ld[lim]=dict()
                    self.ld[lim][x[-1]]=set()
                    self.ld[lim][x[-1]].add(x)
                    
         
        
    def query(self, letter: str) -> bool:
        self.s+=letter
        self.c+=1
        ###print(self.s,self.c)
        
        for y in self.lths:
            
            if y<=self.c:
                ###print(self.s[-y:])
                if self.s[-1] in self.ld[y]:
                    if self.s[-y:] in self.ld[y][self.s[-1]]:

                        return True
                
        
        return False
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


'''
Keep a list of prefixes and pop one letter at a time, if 

keep a dict of next letters with the values as the next to pop
'''
class StreamChecker:

    def __init__(self, words: List[str]):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in words: reduce(dict.__getitem__, w, self.trie)['#'] = True
        self.waiting = []

    def query(self, letter):
        self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any(\"#\" in node for node in self.waiting)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

from collections import defaultdict

def routing():
    return defaultdict(routing)


class StreamChecker:
    def __init__(self, words: List[str]):
        self.router = routing()
        #print(f'{words=}')
        for word in words:
            root = self.router
            for letter in word:
                root = root[letter]
            root[\"*\"] = word
        self.queries = []

    def query(self, letter: str) -> bool:
        #print(f'{letter=} {len(self.queries)=}')
        new_queries, matches = [], []
        self.queries.append(self.router)
        for q in self.queries:
            if letter in q:
                q = q[letter]
                if '*' in q:
                    matches.append(q[\"*\"])
                    if len(q) > 1:
                        new_queries.append(q)
                else:
                    new_queries.append(q)
        self.queries = new_queries
        #print(f'{matches=}')
        return bool(matches)


class Trie:
    def __init__(self):
        self.trie = {}
    def insert(self,w):
        t = self.trie
        for c in w+'\\0':
            if c not in t: t[c] = {}
            t = t[c]

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        for word in words:
            self.trie.insert(word)
        self.nodes = [self.trie.trie]
            
    def query(self, letter: str) -> bool:
        newNodes = [self.trie.trie]
        ret = False
        for node in self.nodes:
            if letter in node:
                newNodes.append(node[letter])  
                if '\\0' in node[letter]: ret = True
        self.nodes = newNodes
        return ret
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode():
    def __init__(self):
        self.children = {}
        self.isEnd = False

class Trie():
    def __init__(self):
        self.root = TrieNode()
    
    def insert(self, word):
        node = self.root
        for char in word:
            if char not in node.children:
                node.children[char] = TrieNode()
            node = node.children[char]
        node.isEnd = True

class StreamChecker:
    def __init__(self, words: List[str]):
        self.letters = []
        self.trie = Trie()
        for w in words:
            self.trie.insert(w[::-1])
        
    def query(self, letter: str) -> bool:
        self.letters.append(letter)
        i = len(self.letters) - 1
        node = self.trie.root
        while i >= 0:
            if node.isEnd:
                return True
            if self.letters[i] not in node.children:
                return False
            node = node.children[self.letters[i]]
            i -= 1
        return node.isEnd
        

    \"\"\"def query(self, letter: str) -> bool:
        self.chars.append(letter)
        s = \"\".join(self.chars)
        #print(s)
        for i in range(len(s)):
            #print(\"s[i:] is \" + s[i:])
            for word in self.words:        
                if s[i:] == word or s[len(s) - i:] == word:
                    return True
        return False
    \"\"\"


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self):
        self.children = [None] * 26
        self.last = False

class Trie:
    def __init__(self):
        self.root = TrieNode()
    
    def insert(self, word):
        node = self.root
        
        for ch in word:
            idx = ord(ch) - ord('a')
            if not node.children[idx]:
                node.children[idx] = TrieNode()
            node = node.children[idx]
        
        node.last = True
    
    def search(self, word):
        node = self.root
        for ch in word:
            idx = ord(ch) - ord('a')
            if not node.children[idx]:
                return False
            node = node.children[idx]
            
            if node.last:
                return True
        
        return False
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        for word in words:
            self.trie.insert(word[::-1])
        
        self.letters = \"\"
        

    def query(self, letter: str) -> bool:
        
        self.letters += letter
        word_to_search = self.letters[::-1]
        
        # print(word_to_search)
        return self.trie.search(word_to_search)
        
        
        
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

_end = '_end_'

class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie = {}
        self.nodes_for_letters = []
        for word in words:
            self.add_to_trie(word)
        
    def add_to_trie(self, word):
        current = self.trie
        for letter in word:
            if letter not in current:
                current[letter] = {}
            current = current[letter]
        current[_end] = _end
    

    def query(self, letter: str) -> bool:
        potential_nodes = self.nodes_for_letters + [self.trie]
        self.nodes_for_letters = [node[letter] for node in potential_nodes if letter in node]
        return any((_end in node) for node in self.nodes_for_letters)
        
            

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self, ch):
        self.val = ch
        self.children = {}
        self.is_word = False

class Trie:
    def __init__(self):
        self.root = TrieNode('')
    
    def insert(self, word):
        curr = self.root
        for ch in word:
            if ch in curr.children:
                curr = curr.children[ch]
            else:
                curr.children[ch] = TrieNode(ch)
                curr = curr.children[ch]
        curr.is_word = True
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        for word in words:
            self.trie.insert(word[::-1])
        self.string = ''

    def query(self, letter: str) -> bool:
        self.string += letter
        curr = self.trie.root
        for ch in self.string[::-1]:
            if ch in curr.children:
                curr = curr.children[ch]
                if curr.is_word:
                    return True
            else:
                return False
        return curr.is_word


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import defaultdict

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.previous = []
        for word in words:
            path = self.trie
            for letter in word:
                if letter not in path:
                    path[letter] = {}
                    
                path = path[letter]
            path[\"END\"] = {}

    def query(self, letter: str) -> bool:
        found = False
        
        next = []
        for previous in self.previous:
            if letter in previous:
                if \"END\" in previous[letter]:
                    found = True
                #print(f\"test: {letter}, {previous[letter]}\")
                next.append(previous[letter])
        self.previous = next
        
        if letter in self.trie:
            if \"END\" in self.trie[letter]:
                found = True
            self.previous.append(self.trie[letter])
        
        #print(f\"{letter}: {found}, {self.previous}\")
        return found
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:
    def __init__(self, words: List[str]):
        self.tree = Tree('0', [])
        for item in words:
            curr = self.tree
            for letter in item[::-1]:
                result = curr.in_list(letter)
                if result is None:
                    curr.subtrees.append(Tree(letter, []))
                    curr = curr.subtrees[-1]
                else:
                    curr = curr.subtrees[result]
            curr.food = True
        self.q = ''

    def query(self, letter: str) -> bool:
        self.q += letter
        reverse_q = self.q[::-1]
        curr = self.tree
        for letter in reverse_q:
            result = curr.in_list(letter)
            if result is None:
                return False
            else:
                curr = curr.subtrees[result]
                if curr.food:
                    return True
        return False

class Tree:
    def __init__(self, root, subtrees):
        self.root = root
        self.food = False
        self.subtrees = subtrees

    def in_list(self, letter: str):
        for i, item in enumerate(self.subtrees):
            if item.root == letter:
                return i
        return None


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            node = self.trie
            for i, c in enumerate(word):
                if c not in node:
                    node[c] = {}
                node = node[c]
                if i == len(word)-1:
                    node[\"#\"] = {}
        print(self.trie)        
        self.candidates = [self.trie]

    def query(self, letter: str) -> bool:
        new_candidates = [self.trie]
        word_found = False
        for node in self.candidates:
            if letter in node:
                new_candidates.append(node[letter])
                if \"#\" in node[letter]:
                    word_found = True
        self.candidates = new_candidates
        return word_found


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self):
        self.children = {}
        self.end_node = False

class Trie:
    def __init__(self):
        self.root = TrieNode()
    
    def insert(self, word):
        cur = self.root
        for c in word:
            if not (c in cur.children):
                cur.children[c] = TrieNode()
            cur = cur.children[c]
        cur.end_node = True
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.str = \"\"
        for word in words:
            self.trie.insert(word[::-1])
        

    def query(self, letter: str) -> bool:
        self.str += letter
        cur = self.trie.root
        for c in self.str[::-1]:
            if(c in cur.children):
                cur = cur.children[c]
                if(cur.end_node):
                    return True
            else:
                break
        return False       
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode():
    import collections
    def __init__(self):
        self.children = collections.defaultdict(TrieNode)
        self.is_word = False
class Trie():
    def __init__(self):
        self.root = TrieNode()
    def construct(self,word):
        node = self.root
        for c in word[::-1]:
            node = node.children[c]
        node.is_word = True
    
    
class StreamChecker:

    def __init__(self, words: List[str]):
        self.tree = Trie()
        self.letters = []
        for word in words:
            self.tree.construct(word)

    def query(self, letter: str) -> bool:
        self.letters.append(letter)
        
        if letter in self.tree.root.children:
            node = self.tree.root
            for l in self.letters[::-1]:
                node = node.children.get(l)
                if not node:
                    return False
                if node.is_word:
                    return True
            return node.is_word
        return False
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            cur = self.trie
            for char in word:
                if char not in cur:
                    cur[char] = {}
                cur = cur[char]
            cur['~'] = word
            
        self.candidates = []

    def query(self, letter: str) -> bool:
        newCands = []
        foundWord = False
        
        if letter in self.trie:
            newCands.append(self.trie[letter])
            if '~' in self.trie[letter]:
                foundWord = True
                
        for cand in self.candidates:
            if letter in cand:
                newCands.append(cand[letter])
                if '~' in cand[letter]:
                    foundWord = True
        
        self.candidates = newCands
        return foundWord


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode():
    def __init__(self):
        self.children = collections.defaultdict()
        self.isEnd = False

class Trie():
    def __init__(self):
        self.root = TrieNode()
    
    def insert(self, word):
        node = self.root
        for char in word:
            if char not in node.children:
                node.children[char] = TrieNode()
            node = node.children[char]
        node.isEnd = True

class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.maxlen = 0
        self.cache = collections.deque()
        for w in words:
            self.trie.insert(w[::-1])
            self.maxlen = max(self.maxlen, len(w))
        
    def query(self, letter: str) -> bool:
        self.cache.append(letter)
        if len(self.cache) > self.maxlen:
            self.cache.popleft()
        i = len(self.cache) - 1
        node = self.trie.root
        while i >= 0:
            if node.isEnd:
                return True
            if self.cache[i] not in node.children:
                return False
            node = node.children[self.cache[i]]
            i -= 1
        return node.isEnd
 

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            cur = self.trie
            for ch in word:
                if ch not in cur:
                    cur[ch] = {}
                cur = cur[ch]
            cur['#'] = '#'
        self.queue = []

    def query(self, letter: str) -> bool:
        res = False
        nxt = []
        for top in self.queue:
            if letter in top:
                if '#' in top[letter]:
                    res = True
                nxt.append(top[letter])
        if letter in self.trie:
            if '#' in self.trie[letter]:
                res = True
            nxt.append(self.trie[letter])
        self.queue = nxt
        return res


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = self._trie()
        self._fillTrie(words)
        self.q = []
        
    def _trie(self):
        return defaultdict(self._trie)
    
    def _fillTrie(self, words):
        for w in words:
            t = self.trie
            for c in w:
                t = t[c]
            t['*']
            
    def query(self, letter: str) -> bool:
        found,newQ = False,[]
        self.q.append(self.trie)
        
        for t in self.q:
            if letter in t:
                t = t[letter]
                newQ.append(t)
                found |= '*' in t
        self.q = newQ
        return found
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    def __init__(self):
        self.trie = {}
        
    def add_word(self,word):
        nextLevel = self.trie
        for i,char in enumerate(word):
            isWord = i == len(word) - 1
            if char not in nextLevel:
                nextLevel[char] = {}
            if isWord:
                nextLevel[char][\"#\"] = True
            
            nextLevel = nextLevel[char]



class StreamChecker:

    def __init__(self, words: List[str]):
        self.words = set(words)
        self.trie = Trie()
        for word in words:
            self.trie.add_word(word)
            
        self.nextLevels = []
        self.count = 0

    def query(self, letter: str) -> bool:
        nextLevels = []
        isWord = False
        if len(self.nextLevels):
            for level in self.nextLevels:
                if letter in level:
                    if \"#\" in level[letter]:
                        isWord = True
                    nextLevels.append(level[letter])
        
        if letter in self.trie.trie:
            nextLevels.append( self.trie.trie[letter] )
            if \"#\" in self.trie.trie[letter]:
                isWord = True
                
        self.nextLevels = nextLevels
    
        return isWord
    





# class Trie:
#     def __init__(self):
#         self.trie = {}
        
#     def add_word(self,word):
#         nextLevel = self.trie
#         for i,char in enumerate(word):
#             isWord = i == len(word) - 1
#             if char in nextLevel:
#                 if isWord:
#                     nextLevel[char].isWord = True
#                 nextLevel = nextLevel[char].children
#             else:
#                 node = TrieNode(char, isWord)
#                 nextLevel[char] = node
#                 nextLevel = nextLevel[char].children
            
        
# class TrieNode:
#     def __init__(self, char, isWord = False):
#         self.char = char
#         self.isWord = isWord
#         self.children = {}


# class StreamChecker:

#     def __init__(self, words: List[str]):
#         self.words = set(words)
#         self.trie = Trie()
#         for word in words:
#             self.trie.add_word(word)
            
#         self.nextLevels = []
#         self.count = 0

#     def query(self, letter: str) -> bool:
#         nextLevels = []
#         isWord = False
#         if len(self.nextLevels):
#             for level in self.nextLevels:
#                 if letter in level:
#                     if level[letter].isWord:
#                         isWord = True
#                     nextLevels.append(level[letter].children)
        
#         if letter in self.trie.trie:
#             nextLevels.append( self.trie.trie[letter].children )
#             if self.trie.trie[letter].isWord:
#                 isWord = True
                
#         self.nextLevels = nextLevels
    
#         return isWord
    


from collections import defaultdict
class StreamChecker:
    # Time: O(qn), q = queries performed, n is amt words
    # Space: O(nw), n is amt words, w is largest word
    # Runtime: 9000ms beats 0% lol
    def __init__(self, words: List[str]):
        self.trie = self._trie()
        self._fillTrie(words)
        self.q = []
        
    def _trie(self):
        return defaultdict(self._trie)
    
    def _fillTrie(self, words):
        for w in words:
            t = self.trie
            for c in w:
                t = t[c]
            t['*']
            
    def query(self, letter: str) -> bool:
        found,newQ = False,[]
        self.q.append(self.trie)
        
        for t in self.q:
            if letter in t:
                t = t[letter]
                newQ.append(t)
                found |= '*' in t
        self.q = newQ
        return found

END = '_'

class StreamChecker:    
    def __init__(self, words: List[str]):
        self.tree = {}
        self.queries = []
        
        for w in words:
            sub = self.tree
            for c in w:
                if c not in sub: sub[c] = {}
                sub = sub[c]
            sub[END] = END
        
    def query(self, l: str) -> bool:
        found = False
        
        self.queries.append(self.tree)
        
        qs = []
        
        for q in self.queries:
            if l in q:
                qs.append(q[l])
                if END in q[l]: found = True
        
        self.queries = qs
                
        return found


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.stream = deque([])
        
        for word in set(words):
            node = self.trie
            for ch in word[::-1]:
                if not ch in node:
                    node[ch] = {}
                node = node[ch]
            node['$'] = word
            

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        
        node = self.trie
        for ch in self.stream:
            if '$' in node:
                return True
            if not ch in node:
                return False
            node = node[ch]
        return '$' in node
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.isEnd = False
        self.children = dict()

class Trie:
    def __init__(self):
        self.root = TrieNode()
        
    def addNode(self,word):
        curNode = self.root
        for char in word:
            if char not in curNode.children:
                curNode.children[char] = TrieNode()
            curNode = curNode.children[char]
        curNode.isEnd = True
        
    def search(self,word):
        curNode = self.root
        for char in word:
            
            if char not in curNode.children: return False
            else:
                curNode = curNode.children[char]
                if curNode.isEnd: return True
                else: pass
        return curNode.isEnd

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        for word in words:
            self.trie.addNode(word[::-1])
        self.curWord = ''

    def query(self, letter: str) -> bool:
        self.curWord = letter + self.curWord
        return self.trie.search(self.curWord)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = collections.defaultdict(dict)
        self.construct_trie(words)
        self.l = []
        
    def construct_trie(self, words):
        for word in words:
            t = self.trie
            for w in word:
                if(w not in t):
                    t[w] = {}
                t = t[w]
            t['$'] = True
        
        print((self.trie))
        
    def query(self, letter: str) -> bool:
        t = self.trie
        ans  = False
        
        temp = []
        for d in self.l:
            if(letter in d):
                if('$' in d[letter]):
                    ans = True
                temp.append(d[letter])
        self.l = temp
        if(letter in t):
            self.l.append(t[letter])
            if('$' in t[letter]):
                return True
        return ans
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.words = list(set(words))
        self.n = max(map(len, words))
        self.historic = \"\"

    def query(self, letter: str) -> bool:
        self.historic = self.historic + letter
        if len(self.historic)>self.n:
            self.historic = self.historic[1:]
        for w in self.words:
            if self.historic[-len(w):] == w:
                return True
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        from collections import defaultdict
        self.trie = dict()
        
        for word in words:
            trie = self.trie
            for c in word:
                if c not in trie:
                    trie[c] = dict()
                    trie[c]['word'] = False
                trie = trie[c]
            trie['word'] = True
        
        self.tries = list()
        #print(self.trie)
        # self.words = {word:0 for word in words}
        # self.possible = list()
        # self.maxsize = max([len(word) for word in words])

    def query(self, letter: str) -> bool:
        newtries = list()
        self.tries.append(self.trie)
        found = False
        for trie in self.tries:
            if letter in trie:
                newtries.append(trie[letter])
                if trie[letter]['word']:
                    found = True
        self.tries = newtries
        # self.possible.append('')
        # newposs = list()
        # found = False
        # for pos in self.possible:
        #     pos += letter
        #     if pos in self.words:
        #         found = True
        #     if len(pos) <= self.maxsize:
        #         newposs.append(pos)
        # self.possible = newposs
        return found 


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = dict()
        for word in words:
            node = self.trie
            for c in word:
                if c not in node:
                    node[c] = dict()
                node = node[c]
            node['.'] = '.'

        self.curs = []

    def query(self, letter: str) -> bool:
        trie, curs = self.trie, self.curs
        
        curs = [cur[letter] for cur in curs if letter in cur]
        if letter in trie:
            curs.append(trie[letter])
        self.curs = curs

        return any('.' in cur for cur in curs)

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import defaultdict
class StreamChecker:

    def __init__(self, words):
        tr = lambda: defaultdict(tr)
        self.trie = tr()
        for w in words:
            cur_trie = self.trie[w[0]]
            for i in range(1, len(w)):
                cur_trie = cur_trie[w[i]]
            cur_trie['end'] = True
        self.tail = []

    def query(self, letter):
        self.tail = [node[letter] for node in self.tail + [self.trie] if letter in node]
        for node in self.tail:
            if 'end' in node:
                return True
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie_head = {}
        self.trie_leaf = '$'
        
        for word in words:
            trie_node = self.trie_head
            
            for c in word:
                trie_node = trie_node.setdefault(c, {})
            
            trie_node[self.trie_leaf] = self.trie_leaf
        
        self.trie_pointers = []
        

    def query(self, letter: str) -> bool:
        # Advance all existing pointers
        self.trie_pointers = [trie_node[letter] for trie_node in self.trie_pointers if letter in trie_node]
        
        if letter in self.trie_head:
            self.trie_pointers.append(self.trie_head[letter])
            
        return any([(self.trie_leaf in trie_node) for trie_node in self.trie_pointers])


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):     
        self.waitlist = []
        self.trie = dict()
        for word in words:
            # create a temporary dict based off our root dict object
            temp_dict = self.trie
            for letter in word:
                # update our temporary dict and add our current letter and a sub-dictionary
                # if key is not in dict, setdefault() will add {key:{}} and return default value {}
                # otherwise it will directly return the existing value of key
                temp_dict = temp_dict.setdefault(letter, dict())
            # If our word is finished, add {'#': '#'} at the stopping node
            temp_dict['#'] = '#'

    def query(self, letter):
        waitlist = []
        # if letter can be the prefix of word
        if letter in self.trie:
            waitlist.append(self.trie[letter])
        # for each possible prefix, append letter if the new substr still can be a prefix
        for item in self.waitlist:
            if letter in item:
                waitlist.append(item[letter])
                
        self.waitlist = waitlist
        return any('#' in item for item in self.waitlist)
    
#         self.words = defaultdict(str)
#         self.querying = defaultdict(list)
#         for word in words:
#             if (len(word)>1):
#                 self.words[word[0]] = word[1:]
#             else:
#                 self.words[word[0]] = \"\"
#         print(self.words)
            
#     def query(self, letter: str) -> bool:
#         #need a new flag
#         self.querying[letter] += self.words[letter]
#         if (self.querying[letter] or letter in self.query.keys()):
#             bucket = []
#             print(self.querying[letter])
#             for seq in self.querying[letter]:
#                 print(seq)
#                 if len(seq) == 1:
#                     return True
#                 elif seq[0] == letter:
#                     bucket.append(letter)
#                 elif len(seq)>1:
#                     self.querying[seq[0]] += seq[1:]
#             self.querying[letter] = bucket
            
#         return False
        
        

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.check = []
        for w in words:
            d = self.trie
            for c in w:
                _d = d.get(c, {})
                d[c] = _d
                d = _d
            d['.'] = True
        print((self.trie))

    def query(self, letter: str) -> bool:
        next_check = []
        found = False
        for d in self.check + [self.trie]:
            if letter in d:
                _d = d[letter]
                if '.' in _d:
                    found = True
                next_check.append(_d)
        self.check = next_check
        return found

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
    END = 0
    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            ptr = self.trie
            for letter in word:
                if letter not in ptr:
                    ptr[letter] = {}
                ptr = ptr[letter]
            ptr[StreamChecker.END] = True
        self.working_list = []

    def query(self, letter: str) -> bool:
        is_word = False
        new_working_list = []
        self.working_list.append(self.trie)
        for working_ptr in self.working_list:
            if letter in working_ptr:
                new_working_ptr = working_ptr[letter]
                new_working_list.append(new_working_ptr)
                if StreamChecker.END in new_working_ptr:
                    is_word = True
        
        self.working_list = new_working_list
        return is_word
            
            
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.Trie = dict()
        for word in words:
            t = self.Trie
            for c in word:
                if c not in t:
                    t[c] = dict()
                t = t[c]
            t['$'] = word
        
        self.cache = []

    def query(self, letter: str) -> bool:
        newcache = []
        ret = False
        for t in self.cache + [self.Trie]:
            if letter in t:
                newcache.append(t[letter])
                if '$' in t[letter]:
                    ret = True
        self.cache = newcache
        return ret

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode():
    def __init__(self):
        self.children = collections.defaultdict()
        self.isEnd = False

class Trie():
    def __init__(self):
        self.root = TrieNode()
    
    def insert(self, word):
        node = self.root
        for char in word:
            if char not in node.children:
                node.children[char] = TrieNode()
            node = node.children[char]
        node.isEnd = True

class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.maxlen = 0
        self.cache = []
        for w in words:
            self.trie.insert(w[::-1])
            self.maxlen = max(self.maxlen, len(w))
        
    def query(self, letter: str) -> bool:
        self.cache.append(letter)
        i = len(self.cache) - 1
        node = self.trie.root
        while i >= 0:
            if node.isEnd:
                return True
            if self.cache[i] not in node.children:
                return False
            node = node.children[self.cache[i]]
            i -= 1
        return node.isEnd


class StreamChecker:

    def __init__(self, words: List[str]):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in words: reduce(dict.__getitem__, w, self.trie)['#'] = True
        self.waiting = []
            

    def query(self, letter: str) -> bool:
        self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any(\"#\" in node for node in self.waiting)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            curr = self.trie
            for char in word:
                if char not in curr:
                    curr[char] = {}
                curr = curr[char]
            curr[\"$\"] = True
        self.prev_tries = []
        

    def query(self, letter: str) -> bool:
        curr_trie = []
        self.prev_tries.append(self.trie)
        is_present = False
        
        for trie in self.prev_tries:
            if letter in trie:
                if  '$' in trie[letter]:
                    is_present = True
                curr_trie.append(trie[letter])
        
        self.prev_tries = curr_trie[:]
        
        return is_present

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

from typing import List


class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = dict()

        for word in words:
            root = self.root
            for c in word:
                if c not in root:
                    root[c] = dict()
                root = root[c]
            root['$'] = '.'
        
        self.searches = []
        

    def query(self, letter: str) -> bool:
        searches = self.searches
        searches.append(self.root)

        found = False
        updated_searches = []
        for search in searches:
            if letter not in search:
                continue
            search = search[letter]
            updated_searches.append(search)
            if '$' in search:
                found = True
        self.searches = updated_searches
        
        return found



class Trie:

    def __init__(self, val=''):
        \"\"\"
        Initialize your data structure here.
        \"\"\"
        self.val = val
        self.children = {}
        self.is_end = False

    def insert(self, word: str) -> None:
        \"\"\"
        Inserts a word into the trie.
        \"\"\"
        node = self
        i = 0
        while i < len(word) and word[i] in node.children:
            node = node.children[word[i]]
            i += 1
        for j in range(i, len(word)):
            node.children[word[j]] = Trie(word[j])
            node = node.children[word[j]]
        node.is_end = True

    def search(self, word: str) -> bool:
        \"\"\"
        Returns if the word is in the trie.
        \"\"\"
        node = self
        for lett in word:
            if lett not in node.children:
                return False
            node = node.children[lett]
        return node.is_end
    
    def cutIfStartsWith(self, prefix: str) -> bool:
        \"\"\"
        Returns if there is any word in the trie that starts with the given prefix.
        \"\"\"
        node = self
        for lett in prefix:
            if lett not in node.children:
                return False
            node = node.children[lett]
        node.children = {}
        node.is_end = True
        return True

class StreamChecker:

    def __init__(self, words: List[str]):
        btrie = Trie()
        for w in words:
            bw = w[::-1]
            if not btrie.cutIfStartsWith(bw):
                btrie.insert(bw)
        def get_words(trie):
            return [''] if trie.is_end else [tail + c for c in trie.children for tail in get_words(trie.children[c])]
        self.trie = Trie()
        for w in get_words(btrie):
            self.trie.insert(w)
        self.cur = set()
        

    def query(self, letter: str) -> bool:
        self.cur.add(self.trie)
        self.cur = {t.children[letter] for t in self.cur if letter in t.children}
        for t in self.cur:
            if t.is_end:
                return True
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.d={}
        for w in words:
            cur=self.d    
            for c in w:
                cur.setdefault(c,dict())
                cur=cur[c]
            cur['']=True
        self.q = []
        #print(self.d)

    def query(self, letter: str) -> bool:
        nq=[]
        if letter in self.d:
            nq += [self.d[letter]]
        for pq in self.q:
            if letter in pq:
                nq += [pq[letter]]
        #print(nq,letter)
        self.q=nq
        for qq in self.q:
            if '' in qq: return True
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
    # TODO need proper Aho–Corasick
    # See also contest/weekly182/find-all-good-strings.python3.py
    # TLE, too many prefixes, hard to calculate shared suffixes
    # need a trie instead of set of words. Just building the set takes 2000^3

    def __init__(self, words: List[str]):
        _compress = {}
        _decompress = {}

        def compress(s):
            if s not in _compress:
                i = len(_compress)
                _compress[s] = i
                _decompress[i] = s
            return _compress[s]

        def decompress(i):
            return _decompress[i]

        compress(\"\")

        words = set(words)
        graph = defaultdict(
            lambda: defaultdict(int)
        )  # pref1 -> ch -> pref2 where pref2 is longest word that is a suffix of pref1
        prefs = set()
        for word in words:
            for i in range(len(word) + 1):
                pref = word[:i]
                prefs.add(pref)

        for pref in prefs:
            for i in range(26):
                ch = chr(ord(\"a\") + i)
                for j in range(len(pref) + 1):
                    pref2 = pref[j:] + ch
                    if pref2 in prefs and len(pref2) > len(
                        decompress(graph[compress(pref)][ch])
                    ):
                        graph[compress(pref)][ch] = compress(pref2)

        prefWithWordSuffix = set()
        for pref in prefs:
            for i in range(len(word) + 1):
                if pref[i:] in words:
                    prefWithWordSuffix.add(compress(pref))
                    break
        self.graph = graph
        self.state = compress(\"\")
        self.prefWithWordSuffix = prefWithWordSuffix
        # self.compress = compress
        # self.decompress = decompress

    def query(self, letter: str) -> bool:

        self.state = self.graph[self.state][letter]

        return self.state in self.prefWithWordSuffix


class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            node = self.trie
            for c in word:
                if c not in node:
                    node[c] = {}
                node = node[c]
            node[\"$\"] = word
        self.states = [self.trie]

    def query(self, letter: str) -> bool:
        nextStates = [self.trie]
        for state in self.states:
            if letter in state:
                nextStates.append(state[letter])
        self.states = nextStates
        # print(letter, [state['$'] for state in self.states if '$' in state])
        return any(\"$\" in state for state in self.states)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.nodes = []
        for word in words:
            node = self.trie
            for char in word:
                if char not in node:
                    node[char] = {}
                node = node[char]
            node['end'] = True

    def query(self, letter: str) -> bool:
        self.nodes.append(self.trie)
        temp = False
        new_nodes = []
        
        for node in self.nodes:
            if letter in node:
                node = node[letter]
                if 'end' in node:
                    temp = True
                new_nodes.append(node)
        self.nodes = new_nodes
        return temp



# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


import collections

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.stream = collections.deque()
        self.prefixes = []
        for w in words:
            ptr = self.trie
            for c in w:
                if c not in ptr:
                    ptr[c] = {}
                ptr = ptr[c]
            ptr['#'] = w
            
    def _find_word(self, k: int) -> bool:
        ptr = self.trie
        for c in list(self.stream)[-k:]:
            if c not in ptr:
                return False
            ptr = ptr[c]
        return '#' in ptr

    def query(self, letter: str) -> bool:
        # print(letter)
        if letter in self.trie:
            self.prefixes.append(self.trie)
        valid_prefixes, found = [], False
        for i, ptr in enumerate(self.prefixes):
            # print(f'  {ptr}')
            if letter in ptr:
                ptr = ptr[letter]               
                valid_prefixes.append(ptr)
                if '#' in ptr:
                    found = True
        self.prefixes = valid_prefixes
        return found        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.children = {}
        self.char = None
        self.isEnd = False
    
    def contains(self, c):
        return c in self.children
    
    def set(self, c):
        self.children[c] = TrieNode()
        
    def getChild(self, c):
        return self.children[c]

class Trie:
    def __init__(self):
        self.root = TrieNode()
        
    def insert(self, word):
        if not word:
            return
        word = word[::-1]
        it = self.root
        for c in word:
            if not c in it.children:
                it.children[c] = TrieNode()
                it.children[c].char = c
                
            it = it.children[c]
            
        it.isEnd = True
        #print(\"Inserted \", word, it.char)
                
    def hasAnyPrefix(self, letters):
        #print(\"For \", letters)
        it = self.root
        for c in letters:
            #print(\"Looking at c\", c, it.isEnd)
            if it.isEnd:
                return True
            if not it.contains(c):
                #print(\"Not found \", c)
                return False

            it = it.getChild(c)
        
        return it.isEnd

class StreamChecker:

    def __init__(self, words: List[str]):
        from collections import deque
        self.letters = deque([])
        self.trie = Trie()
        for word in words:
            self.trie.insert(word)

    def query(self, letter: str) -> bool:
        self.letters.appendleft(letter)
        return self.trie.hasAnyPrefix(self.letters)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.waitlist = []
        self.trie = {}
        for word in words:
            t = self.trie
            for char in word:
                if char not in t:
                    t[char] = {}
                t = t[char]
            t['#'] = \"#\"
        
    def query(self, letter: str) -> bool:
        waitlist = []
        if letter in self.trie:
            waitlist.append(self.trie[letter])
        
        for item in self.waitlist:
            if letter in item:
                waitlist.append(item[letter])
        self.waitlist = waitlist
        return any(\"#\" in i for i in self.waitlist)
        

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.pointers = [self.trie]
        for word in words:
            t = self.trie
            for w in word:
                if w not in t:
                    t[w] = {}
                t = t[w]
            t['#'] = '#'
        print((self.trie))
    def query(self, letter: str) -> bool:
        s = [self.trie]
        for ele in self.pointers:
            if letter in ele:
                s.append(ele[letter])
        self.pointers = s
        return any(['#' in ele for ele in self.pointers])
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import defaultdict
class StreamChecker:

    def __init__(self, words: List[str]):
        self.root={'*':'*'}
        for word in words:
            curr_node=self.root
            for letter in word:
                if letter not in curr_node:
                    curr_node[letter]={}
                curr_node=curr_node[letter]
            curr_node[\"*\"]=\"*\"
        self.stream=[]

    def query(self, letter: str) -> bool:
        temp=[]
        self.stream.append(self.root)
        for i in self.stream:
            if letter in i:
                temp.append(i[letter])
        self.stream=temp
        for i in self.stream:
            if \"*\" in i:
                return True
        return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.nodes = []
        for word in words:
            node = self.trie
            for char in word:
                if char not in node:
                    node[char] = {}
                node = node[char]
            node['end'] = True

    def query(self, letter: str) -> bool:
        self.nodes.append(self.trie)
        temp = False
        new_nodes = []
        
        for node in self.nodes:
            if letter in node:
                node = node[letter]
                if 'end' in node:
                    temp = True
                new_nodes.append(node)
        self.nodes=new_nodes
        return temp


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.s = set()
        for w in words:
            self.s = self.s.union(set(w))
        self.d = {}   
        for w in words:
            insert(self.d, w)
        self.l = []
        #print(self.d)

    def query(self, letter: str) -> bool:
        if letter not in self.s:
            return False
        d = self.d
        l = self.l
        b = False
        for i in reversed(list(range(len(l)))):
            if letter in l[i]:
                l[i] = l[i][letter]
                if '#' in l[i]:
                    b = True
            else:
                del l[i]
        if letter in d:
            l.append(d[letter])
            if '#' in l[-1]:
                b = True
        return b
def insert(d, s):
    if len(s) == 0:
        d['#'] = {}
    else:
        if s[0] not in d:
            d[s[0]] = {}
        insert(d[s[0]],s[1:])

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for w in words:
            t = self.trie
            for c in w:
                if c not in t:
                    t[c]={}
                t = t[c]
            t['#']='#'
        self.poss = []
                    
    def query(self, letter: str) -> bool:
        
        waitlist = []
        
        if letter in self.trie:
            waitlist.append(self.trie[letter])
            
        for t in self.poss:
            if letter in t:
                waitlist.append(t[letter])
        self.poss = waitlist
        return any('#' in t for t in waitlist)
    
#         ans = False
#         popthis = set()
#         if letter in self.trie:
#             t = self.trie
#             self.poss.append(t)
#         for i in range(len(self.poss)):
#             if letter in self.poss[i]:
#                 self.poss[i]=self.poss[i][letter]
#                 if '#' in self.poss[i]:
#                     ans = True
#             else:
#                 popthis.add(i)
#         new = []
#         for i,x in enumerate(self.poss):
#             if i not in popthis:
#                 new.append(x)
#         self.poss = new
        
#         return ans
        
        
       
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamC'hecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.wordlist = []
        for w in words:
            self.wordlist.append(w[::-1])
        self.wordlist.sort()
        self.history = ''
        
    def query2(self, letter: str) -> bool:
        self.history = letter + self.history
        k = 0
        for i in range(len(self.history)):
            w = self.history[:i+1]
            while w > self.wordlist[k]:
                k += 1
                if k == len(self.wordlist):
                    return False
            #print(w ,self.wordlist,k)
            if w == self.wordlist[k]:
                return True
        return False
    
    def query(self, letter: str) -> bool:
        self.history = letter + self.history
        s = 0
        f = len(self.wordlist)
        from bisect import bisect_left
        for i in range(len(self.history)):
            indx = bisect_left(self.wordlist[s:f],self.history[:i+1]) - 1
            #print(self.wordlist[s:f],self.history[:i+1],indx)
            if indx == -1:
                if self.wordlist[s:f][0] == self.history[:i+1]:
                    return True
                #if not self.history[-1] == self.wordlist[s:f][0][-1]:
                 #   print(self.wordlist[s:f],self.history[:i+1],indx)
                    #return False
            if indx+1 < len(self.wordlist[s:f]) and self.wordlist[s:f][indx+1] == self.history[:i+1]:
                return True
            
            
            #print(self.wordlist[s:f],self.history[:i+1],indx)
            tmp = s + indx +1 
            f = s + bisect_left(self.wordlist[s:f], self.history[:i] + chr(ord(self.history[i])+1))
            s = tmp
            #print(s,f)
            if s>=f:
                return False
            #if f-s == 1 and not self.wordlist[s] == self.history[:i+1]:
            #    return False
                
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Node(object):
    def __init__(self):
        self.child = defaultdict(lambda: Node())
        self.leaf = False
    def add(self, word):
        #print(\"add word\", word)
        if len(word) == 0:
            self.leaf = True
        else:
            self.child[word[0]].add(word[1:])
    def query(self, word):
        #print(\"quering word\", word)
        if len(word) == 0:
            return self.leaf
        elif self.leaf:
            return True
        elif word[0] not in self.child:
            return False
        else:
            #print(\"word\",word)
            #print(word[0]) 
            #print(word[1:])
            return self.child[word[0]].query(word[1:])
            
class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = Node()
        self.queue = \"\"
        self.cur = None
        for w in words:
            self.root.add(list(reversed(w)))

    def query(self, letter: str) -> bool:
        self.queue = letter + self.queue
        

        return self.root.query(self.queue)











# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.start = []
        
        for word in words:
            self.add(word)
            
    def add(self, word):
        curr = self.trie
        
        for c in word:
            if c not in curr:
                curr[c] = {}
            curr = curr[c]
        curr['#'] = True
        
    def query(self, letter: str) -> bool:
        
        start = []
        if letter in self.trie:
            start.append(self.trie[letter])
            
        for p in self.start:
            if letter in p:
                start.append(p[letter])
                
        self.start = start
        
        return any('#' in p for p in self.start)

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
  def __init__(self):
    self.children = collections.defaultdict(TrieNode)
    self.end = False

class ReverseTrie:
    
  def __init__(self, words):
    self.root = TrieNode()
    
    for word in words:
      self.add_reverse_word(word)
      
  def add_reverse_word(self, word):
    curr_node = self.root
    
    for idx in range(len(word) - 1, -1, -1):
      char = word[idx]
      curr_node = curr_node.children[char]
      
    curr_node.end = True
    
  def reverse_word_exists(self, reverse_letters):
    reverse_word_found = False
    
    curr_trie_node = self.root
    for idx in range(len(reverse_letters) - 1, -1, -1):
      char = reverse_letters[idx]
      if char in curr_trie_node.children:
        curr_trie_node = curr_trie_node.children[char]
        if curr_trie_node.end:
          return True
        
        idx -= 1
      else:
        return False
      
      
    return False
      
      
class StreamChecker:

    def __init__(self, words: List[str]):
        self.last_n_queries = collections.deque([])
        self.trie_reverse_words = ReverseTrie(words)
        self.max_word_length = 2000

    def query(self, letter: str) -> bool:
      
      self.last_n_queries.append(letter)
      
      if len(self.last_n_queries) > self.max_word_length:
        self.last_n_queries.popleft()
        
      return self.trie_reverse_words.reverse_word_exists(self.last_n_queries)

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

#cd, f, kl


\"\"\"
class Node:
    def __init__(self, c):
        self.char = c
        self.pointers = {}
        self.wordEnd = False

class Trie:
    def __init__(self):
        self.d = {}

    def insert(self, word: str) -> None:
        if not word:
            return
        
        if word[0] not in self.d:
            self.d[word[0]] = Node(word[0])
            
        if len(word) > 1:
            n = self.d[word[0]]
            
            for j, c in enumerate(word[1:]):
                if c in n.pointers:
                    n = n.pointers[c]
                else:
                    n_ = Node(c)
                    n.pointers[c] = n_
                    n = n_
                
                if j+1 == len(word)-1:
                    n.wordEnd = True
        else:
            self.d[word[0]].wordEnd = True

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        for w in words:
            self.trie.insert(w)
        
        self.curNode = None
        
        self.q = []
        

    def getNext(self, letter):        
        if not self.q:
            if letter in self.trie.d:
                self.q.append(self.trie.d[letter])
        else:
            q2 = []
            
            visited =  set()

            for node in self.q:
                for p in node.pointers:                    
                    newNode = node.pointers[p]
                    
                    if newNode in visited:
                        #print (\"duplicate\")
                        continue

                    if newNode.char == letter:
                        q2.append(newNode)
                        visited.add(newNode)
            
            for node in self.trie.d:
                for p in self.trie.d:                    
                    newNode = self.trie.d[p]
                    
                    if newNode in visited:
                        #print (\"duplicate\")
                        continue

                    if newNode.char == letter:
                        q2.append(newNode)
                        visited.add(newNode)

            self.q = q2
        
        
    def query(self, letter: str) -> bool:
        self.getNext(letter)
        return any([x.wordEnd for x in self.q])
\"\"\"

class StreamChecker(object):

    def __init__(self, words):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in words: reduce(dict.__getitem__, w, self.trie)['#'] = True
        self.waiting = []

    def query(self, letter):
        self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any(\"#\" in node for node in self.waiting)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.tries = {}
        for word in words:
            tries = self.tries
            for c in word:
                if c not in tries:
                    tries[c] = {}
                tries = tries[c]
            tries['END'] = 1
        self.pool = []

    def query(self, letter: str) -> bool:
        new_pool = []
        self.pool.append(self.tries)
        for tries in self.pool:
            if letter in tries:
                new_pool.append(tries[letter])
        self.pool = new_pool
        return  any('END' in tries for tries in self.pool)

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker(object):

    def __init__(self, words):
        \"\"\"
        :type words: List[str]
        \"\"\"      
        self.waitlist = []
        self.trie = dict()
        for word in words:
            # create a temporary dict based off our root dict object
            temp_dict = self.trie
            for letter in word:
                # update our temporary dict and add our current letter and a sub-dictionary
                # if key is not in dict, setdefault() will add {key:{}} and return default value {}
                # otherwise it will directly return the existing value of key
                temp_dict = temp_dict.setdefault(letter, dict())
            # If our word is finished, add {'#': '#'} at the stopping node
            temp_dict['#'] = '#'

    def query(self, letter):
        \"\"\"
        :type letter: str
        :rtype: bool
        \"\"\"
        waitlist = []
        # if letter can be the prefix of word
        if letter in self.trie:
            waitlist.append(self.trie[letter])
        # for each possible prefix, append letter if the new substr still can be a prefix
        for item in self.waitlist:
            if letter in item:
                waitlist.append(item[letter])
                
        self.waitlist = waitlist
        return any('#' in item for item in self.waitlist)
    

from typing import List


class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = dict()

        for word in words:
            root = self.root
            for c in word:
                if c not in root:
                    root[c] = dict()
                root = root[c]
            root['$'] = '.'
        
        self.searches = []
        

    def query(self, letter: str) -> bool:
        self.searches.append(self.root)

        found = False
        failed = list()
        i = 0
        for search in self.searches:
            if letter not in search:
                failed.append(i)
            else:
                search = search[letter]
                self.searches[i] = search
                if '$' in search:
                    found = True
            i += 1
        
        o = 0
        for i in failed:
            del self.searches[i - o]
            o += 1
        
        return found



class Trie:
    def __init__(self):
        self.trie = {}
        
    def add_word(self,word):
        nextLevel = self.trie
        for i,char in enumerate(word):
            isWord = i == len(word) - 1
            if char not in nextLevel:
                nextLevel[char] = {}
            if isWord:
                nextLevel[char][\"#\"] = True
            
            nextLevel = nextLevel[char]


class StreamChecker:
    def __init__(self, words: List[str]):
        self.words = set(words)
        self.trie = Trie()
        for word in words:
            self.trie.add_word(word)
            
        self.nextLevels = []
        self.count = 0

    def query(self, letter: str) -> bool:
        nextLevels = []
        isWord = False
        if len(self.nextLevels):
            for level in self.nextLevels:
                if letter in level:
                    if \"#\" in level[letter]:
                        isWord = True
                    nextLevels.append(level[letter])
        
        if letter in self.trie.trie:
            nextLevels.append( self.trie.trie[letter] )
            if \"#\" in self.trie.trie[letter]:
                isWord = True
                
        self.nextLevels = nextLevels
    
        return isWord
    





# class Trie:
#     def __init__(self):
#         self.trie = {}
        
#     def add_word(self,word):
#         nextLevel = self.trie
#         for i,char in enumerate(word):
#             isWord = i == len(word) - 1
#             if char in nextLevel:
#                 if isWord:
#                     nextLevel[char].isWord = True
#                 nextLevel = nextLevel[char].children
#             else:
#                 node = TrieNode(char, isWord)
#                 nextLevel[char] = node
#                 nextLevel = nextLevel[char].children
            
        
# class TrieNode:
#     def __init__(self, char, isWord = False):
#         self.char = char
#         self.isWord = isWord
#         self.children = {}


# class StreamChecker:

#     def __init__(self, words: List[str]):
#         self.words = set(words)
#         self.trie = Trie()
#         for word in words:
#             self.trie.add_word(word)
            
#         self.nextLevels = []
#         self.count = 0

#     def query(self, letter: str) -> bool:
#         nextLevels = []
#         isWord = False
#         if len(self.nextLevels):
#             for level in self.nextLevels:
#                 if letter in level:
#                     if level[letter].isWord:
#                         isWord = True
#                     nextLevels.append(level[letter].children)
        
#         if letter in self.trie.trie:
#             nextLevels.append( self.trie.trie[letter].children )
#             if self.trie.trie[letter].isWord:
#                 isWord = True
                
#         self.nextLevels = nextLevels
    
#         return isWord
    


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = dict()
        self.pointers = []
        for word in words:
            if len(word) == 0:
                continue
            for i, ch in enumerate(word):
                if i == 0:
                    self.trie[ch] = self.trie.get(ch, dict())
                    cur = self.trie[ch]
                else:
                    cur[ch] = cur.get(ch, dict())
                    cur = cur[ch]
            cur['end'] = 1

    def query(self, letter: str) -> bool:
        result = False
        pointers_new = []
        if letter in self.trie:
            pointers_new.append(self.trie[letter])
            if 'end' in self.trie[letter]:
                result = True
                
        for pointer in self.pointers:
            if letter not in pointer:
                continue
            pointers_new.append(pointer[letter])
            if 'end' in pointer[letter]:
                result = True
        self.pointers = pointers_new
        
        return result


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        
        self.l=[]
        self.trie={}
        for word in words:
            self.insert(word)
        
        print(self.trie)
    
    def insert(self, word: str) -> None:
        \"\"\"
        Inserts a word into the trie.
        \"\"\"
        start = self.trie
        for i in word:
            if i not in start:
                start[i] = {}
            start = start[i]
        start['$'] = True
                    

    def query(self, letter: str) -> bool:
        
        t=self.trie
        ans=False
        temp=[]
        for d in self.l:
            if letter in d:
                if \"$\" in d[letter]:
                    ans=True
                temp.append(d[letter])
        
        self.l=temp
        if letter in t:
            self.l.append(t[letter])
            if \"$\" in t[letter]:
                return True
        
        return ans
                
# param_1 = obj.query(letter)

class TrieNode():
    def __init__(self):
        self.children = {}
        self.word = False
        
class Trie():
    def __init__(self):
        self.root = TrieNode()
        
    def insert(self,word):
        node = self.root
        for ch in word:
            if ch not in node.children:
                node.children[ch] = TrieNode()
            node = node.children[ch]
        node.word = True

class StreamChecker:

    def __init__(self, words: List[str]):
        self.letters = []
        self.trie = Trie()
        for w in words:
            self.trie.insert(w[::-1])
        
        

    def query(self, letter: str) -> bool:
        self.letters.append(letter)
        i = len(self.letters)-1
        node = self.trie.root
        while i >=0:
            if node.word:
                return True
            if self.letters[i] not in node.children:
                return False
            node = node.children[self.letters[i]]
            i -= 1
        return node.word


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words):
        \"\"\"
        :type words: List[str]
        \"\"\"      
        self.waitlist = []
        self.trie = dict()
        for word in words:
            # create a temporary dict based off our root dict object
            temp_dict = self.trie
            for letter in word:
                # update our temporary dict and add our current letter and a sub-dictionary
                # if key is not in dict, setdefault() will add {key:{}} and return default value {}
                # otherwise it will directly return the existing value of key
                temp_dict = temp_dict.setdefault(letter, dict())
            # If our word is finished, add {'#': '#'} at the stopping node
            temp_dict['#'] = '#'
            
    def query(self, letter):
        \"\"\"
        :type letter: str
        :rtype: bool
        \"\"\"
        waitlist = []
        # if letter can be the prefix of word
        if letter in self.trie:
            waitlist.append(self.trie[letter])
        # for each possible prefix, append letter if the new substr still can be a prefix
        for item in self.waitlist:
            if letter in item:
                waitlist.append(item[letter])
                
        self.waitlist = waitlist
        return any('#' in item for item in self.waitlist)
    


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words):
        \"\"\"
        :type words: List[str]
        \"\"\"      
        self.waitlist = []
        self.trie = dict()
        for word in words:
            # create a temporary dict based off our root dict object
            temp_dict = self.trie
            for letter in word:
                # update our temporary dict and add our current letter and a sub-dictionary
                # if key is not in dict, setdefault() will add {key:{}} and return default value {}
                # otherwise it will directly return the existing value of key
                temp_dict = temp_dict.setdefault(letter, dict())
            # If our word is finished, add {'#': '#'} at the stopping node
            temp_dict['#'] = '#'

    def query(self, letter):
        \"\"\"
        :type letter: str
        :rtype: bool
        \"\"\"
        waitlist = []
        # if letter can be the prefix of word
        if letter in self.trie:
            waitlist.append(self.trie[letter])
        # for each possible prefix, append letter if the new substr still can be a prefix
        for item in self.waitlist:
            if letter in item:
                waitlist.append(item[letter])
                
        self.waitlist = waitlist
        return any('#' in item for item in self.waitlist)

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker(object):

    def __init__(self, words):
        \"\"\"
        :type words: List[str]
        \"\"\"      
        self.waitlist = []
        self.trie = dict()
        for word in words:  
            temp_dict = self.trie
            for letter in word:
                # update our temporary dict and add our current letter and a sub-dictionary
                # if key is not in dict, setdefault() will add {key:{}} and return default value {}
                # otherwise it will directly return the existing value of key
                temp_dict = temp_dict.setdefault(letter, dict())
            temp_dict['#'] = '#'

    def query(self, letter):
        \"\"\"
        :type letter: str
        :rtype: bool
        \"\"\"
        waitlist = []
        # if letter can be the prefix of word
        if letter in self.trie:
            waitlist.append(self.trie[letter])
        # for each possible prefix, append letter if the new substr still can be a prefix
        for item in self.waitlist:
            if letter in item:
                waitlist.append(item[letter])
                
        self.waitlist = waitlist
        return any('#' in item for item in self.waitlist)

class StreamChecker:
    def __init__(self, words: List[str]):
        self.waitlist=[]
        self.trie=dict()
        for word in words:
            temp=self.trie
            for letter in word:
                temp=temp.setdefault(letter,dict())
            temp[\"%\"]=\"%\"
        print(self.trie)
        
    def query(self, letter: str) -> bool:
        wait=[]
        if letter in self.trie:
            wait.append(self.trie[letter])
        for item in self.waitlist:
            if letter in item:
                wait.append(item[letter])
        self.waitlist=wait
        return any(\"%\" in i for i in self.waitlist)
            
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Node:
    def __init__(self):
        self.children = {}
        self.terminal = False
    def add(self, val):
        self.children[val] = Node()
    def has(self, val):
        return val in list(self.children.keys())
    def get(self, val):
        return self.children[val]
    def set_terminal(self):
        self.terminal = True
    def is_terminal(self):
        return len(self.children) == 0 or self.terminal

class StreamChecker:
    def __init__(self, words: List[str]):
        self.root = Node()
        for word in words:
            curr = self.root
            for sym in word[::-1]:
                if not(curr.has(sym)):
                    curr.add(sym)
                curr = curr.get(sym)
            curr.set_terminal()
        self.prefix = ''

    def query(self, letter: str) -> bool:
        self.prefix += letter
        curr = self.root
        for sym in self.prefix[::-1]:
            if not(curr.has(sym)):
                return False
            curr = curr.get(sym)
            if curr.is_terminal():
                return True
        
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.tree = {}
        for word in words:
            node = self.tree
            for c in word:
                node = node.setdefault(c, {})
            node['#'] = True
        self.active_match = []

    def query(self, letter: str) -> bool:
        assert len(letter) == 1, \"letter should have length 1\"
        to_delete = []
        for i, m in enumerate(self.active_match):
            if letter in m:
                self.active_match[i] = m[letter]
            else:
                to_delete.append(i)
        for i in reversed(to_delete):
            self.active_match[i] = self.active_match[-1]
            self.active_match.pop()
        if letter in self.tree:
            self.active_match.append(self.tree[letter])
        for m in self.active_match:
            if '#' in m:
                return True
        return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.words = set(words)
        self.hist = ''
        

    def query(self, letter: str) -> bool:
        self.hist += letter
        for word in self.words:
            if self.hist[-len(word):] == word:
                return True
        
        return False



# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.watchlist = []
        self.trie = {}
        for word in words:
            temp = self.trie
            for c in word:
                temp.setdefault(c, {})
                temp = temp[c]
            temp.setdefault(\"#\",)
        

    def query(self, letter: str) -> bool:
        watchlist = []
        
        if letter in self.trie:
            watchlist.append(self.trie[letter])

        for node in self.watchlist:
            if letter in node:
                watchlist.append(node[letter])

        self.watchlist = watchlist
        
        return any(\"#\" in n for n in self.watchlist)
            
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Node:
    def __init__(self):
        self.next = {}
        self.isWord = False


class StreamChecker:
    def __init__(self, words: List[str]):
        self.root = Node()
        self.ptr = self.root
        self.letters = []

        for w in words:
            node = self.root
            for c in w[::-1]:
                if c not in node.__next__:
                    node.next[c] = Node()
                node = node.next[c]
            node.isWord = True

    def query(self, letter: str) -> bool:
        self.letters.append(letter)
        idx, ptr = 0, self.root
        N = len(self.letters)

        for i in range(N - 1, -1, -1):
            c = self.letters[i]
            idx += 1
            if c not in ptr.__next__:
                return False
            ptr = ptr.next[c]
            if idx > 0 and ptr.isWord:
                return True
        return False
    
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
    
    def __init__(self, words):
        self.waitlist = [] 
        self.trie = dict()
        
        for word in words: 
            tmp_dict = self.trie
            for c in word : 
                # update our temporary dict and add our current letter and a sub-dictionary
                # if key is not in dict, setdefault() will add {key:{}} and return default value {}
                # otherwise it will directly return the existing value of key
                tmp_dict = tmp_dict.setdefault(c, dict())
            
            tmp_dict['#'] = '#'
        
        
    def query(self, letter: str) -> bool:        
        waitlist = [] 
        
        if letter in self.trie:
            waitlist.append(self.trie[letter])
        
        
        for item in self.waitlist:
            if letter in item : 
                waitlist.append(item[letter])
        
        
        self.waitlist = waitlist
        
        return any('#' in item for item in self.waitlist)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.waitlist = []
        self.trie = dict()
        for word in words:
            temp_dict = self.trie
            for letter in word:
                temp_dict = temp_dict.setdefault(letter, dict())
            temp_dict['#'] = '#'

    def query(self, letter):
        \"\"\"
        :type letter: str
        :rtype: bool
        \"\"\"
        waitlist = []
        if letter in self.trie:
            waitlist.append(self.trie[letter])
        for item in self.waitlist:
            if letter in item:
                waitlist.append(item[letter])
                
        self.waitlist = waitlist
        return any('#' in item for item in self.waitlist)

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

import collections
class StreamChecker:

    def __init__(self, words: List[str]):
        self.waitlist=[]
        self.trie={}
        
        
        for word in words:
            t=self.trie
            for letter in word:
                \"\"\"if letter not in t:
                    t[letter]={}
                t=t[letter]\"\"\"
                t = t.setdefault(letter, {})
            t['#']='#'    
        #print('t',t)        
        #for word in words:
            #self.insert(word)
    def query(self, letter):

            waitlist = []
            # if letter can be the prefix of word
            if letter in self.trie:
                waitlist.append(self.trie[letter])
            # for each possible prefix, append letter if the new substr still can be a prefix
            for item in self.waitlist:
                if letter in item:
                    waitlist.append(item[letter])

            self.waitlist = waitlist
            return any('#' in item for item in self.waitlist)



    # Your StreamChecker object will be instantiated and called as such:
    # obj = StreamChecker(words)
    # param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.waitlist = []
        self.trie = dict()
        for word in words:
            # create a temporary dict based off our root dict object
            temp_dict = self.trie
            for letter in word:
                # update our temporary dict and add our current letter and a sub-dictionary
                # if key is not in dict, setdefault() will add {key:{}} and return default value {}
                # otherwise it will directly return the existing value of key
                temp_dict = temp_dict.setdefault(letter, dict())
            # If our word is finished, add {'#': '#'} at the stopping node
            temp_dict['#'] = '#'
        

    def query(self, letter: str) -> bool:
        waitlist = []
        # if letter can be the prefix of word
        if letter in self.trie:
            waitlist.append(self.trie[letter])
        # for each possible prefix, append letter if the new substr still can be a prefix
        for item in self.waitlist:
            if letter in item:
                waitlist.append(item[letter])
                
        self.waitlist = waitlist
        return any('#' in item for item in self.waitlist)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        
        for word in words:
            node = self.trie
            for c in word:
                if c not in node:
                    node[c] = {}
                node = node[c]
            node['#'] = {}
        
        self.table = []
        

    def query(self, letter: str) -> bool:
        
        tmp = []
        
        for node in self.table + [self.trie]:
            if letter in node:
                tmp.append(node[letter])
        self.table = tmp
        return any('#' in node for node in self.table)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker(object):

    def __init__(self, words):
        \"\"\"
        :type words: List[str]
        \"\"\"      
        self.waitlist = []
        self.trie = dict()
        for word in words:
            # create a temporary dict based off our root dict object
            temp_dict = self.trie
            for letter in word:
                # update our temporary dict and add our current letter and a sub-dictionary
                # if key is not in dict, setdefault() will add {key:{}} and return default value {}
                # otherwise it will directly return the existing value of key
                temp_dict = temp_dict.setdefault(letter, dict())
            # If our word is finished, add {'#': '#'} at the stopping node
            temp_dict['#'] = '#'

    def query(self, letter):
        \"\"\"
        :type letter: str
        :rtype: bool
        \"\"\"
        waitlist = []
        # if letter can be the prefix of word
        if letter in self.trie:
            waitlist.append(self.trie[letter])
        # for each possible prefix, append letter if the new substr still can be a prefix
        for item in self.waitlist:
            if letter in item:
                waitlist.append(item[letter])
                
        self.waitlist = waitlist
        return any('#' in item for item in self.waitlist)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

def ctoi(c):
    return ord(c)-97
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = [None]*27
        for w in words:
            curr_trie = self.trie
            for c in w:
                c_idx = ctoi(c)
                if not curr_trie[c_idx]:
                    curr_trie[c_idx] = [None]*27
                curr_trie = curr_trie[c_idx]
            curr_trie[-1] = True
        
        self.ptrs = []
    def query(self, letter: str) -> bool:
        found = False
        self.ptrs.append(self.trie)
        new_ptrs = []
        c_idx = ctoi(letter)
        
        for ptr in self.ptrs:
            if ptr[c_idx]:
                new_ptrs.append(ptr[c_idx])
                if ptr[c_idx][-1]:
                    found = True
        
        self.ptrs = new_ptrs
        
        return found
        
            
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import deque, defaultdict
class StreamChecker:

    def __init__(self, words: List[str]):
        # self.words = words
        # self.stream = deque(maxlen=2000)
        self.stream = deque(maxlen=2000)
        
        # organize based on last letter
        self.words_dict = defaultdict(list)
        for word in words:
            self.words_dict[word[-1]].append(word)

    def query(self, letter: str) -> bool:
        
        self.stream.append(letter)
        
        # for word in self.words:
        for word in self.words_dict[letter]:
            if len(word) <= len(self.stream):
                for i in range(len(word)):
                    if word[-(i+1)] != self.stream[-(i+1)]:
                        break
                else:
                    return True
                # if word == ''.join(self.stream[-len(word):]):
                #     return True
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker(object):

    def __init__(self, words):
        \"\"\"
        :type words: List[str]
        \"\"\"      
        self.waitlist = []
        self.trie = dict()
        for word in words:
            # create a temporary dict based off our root dict object
            temp_dict = self.trie
            for letter in word:
                # update our temporary dict and add our current letter and a sub-dictionary
                # if key is not in dict, setdefault() will add {key:{}} and return default value {}
                # otherwise it will directly return the existing value of key
                temp_dict = temp_dict.setdefault(letter, dict())
            # If our word is finished, add {'#': '#'} at the stopping node
            temp_dict['#'] = '#'

    def query(self, letter):
        \"\"\"
        :type letter: str
        :rtype: bool
        \"\"\"
        waitlist = []
        # if letter can be the prefix of word
        if letter in self.trie:
            waitlist.append(self.trie[letter])
        # for each possible prefix, append letter if the new substr still can be a prefix
        for item in self.waitlist:
            if letter in item:
                waitlist.append(item[letter])
                
        self.waitlist = waitlist
        return any('#' in item for item in self.waitlist)
    

    # TLE
# class StreamChecker:

#     def __init__(self, words: List[str]):
#         self.wordDict = set(words)
#         self.streamDict = set()

#     def query(self, letter: str) -> bool:
#         existingKeys = list(self.streamDict)
#         newStreamDict = set()
#         found = False
#         for key in existingKeys+['']:
#             newStreamDict.add(key+letter)
#             if key+letter in self.wordDict:
#                 found = True
#         # print(newStreamDict)
#         self.streamDict = newStreamDict
#         return found


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.memo = {}
        self.words = set()
        words_ = [word[::-1] for word in set(words)]
        for word in words_:
            for i in range(len(word)-1):
                self.memo[word[:i+1]]=0
        
        for word in words_:
            self.memo[word]=1     
        
        self.hist = deque()
        
        #print(self.memo)
    
    def query(self, letter: str) -> bool:
        self.hist.appendleft(letter)
        w = ''
        for i in range(len(self.hist)):
            w+=self.hist[i]
            #print(w)
            c = self.memo.get(w,None)
            if c is None:
                return False
            if c:
                return True
            
        return False


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            ptr = self.trie
            for ch in word:
                if ch not in ptr:
                    ptr[ch] = {}
                ptr = ptr[ch]
            ptr[None] = {}
            
        self.ptrs = []

    def query(self, letter: str) -> bool:
        ptrs = []
        ret = False
        for ptr in self.ptrs:
            if letter in ptr:
                ptrs.append(ptr[letter])
                ret |= None in ptr[letter]
            
        if letter in self.trie:
            ptrs.append(self.trie[letter])
            ret |= None in self.trie[letter]
        
        self.ptrs = ptrs
        return ret

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = dict()
        for w in words:
            curr = self.trie
            for c in w:
                curr = curr.setdefault(c, {})
            curr['$'] = '$'
        self.ptrs = []

    def query(self, letter: str) -> bool:
        ret, new_list = False, []
        self.ptrs.append(self.trie)
        for ptr in self.ptrs:
            if letter in ptr:
                ptr = ptr[letter]
                if '$' in ptr:
                    ret = True
                new_list.append(ptr)
        self.ptrs = new_list
        return ret

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            cur = self.trie
            for c in word:
                if c not in cur:
                    cur[c] = {}
                cur = cur[c]
            cur[\"-\"] = True
        self.currents = [self.trie]

    def query(self, letter: str) -> bool:
        keep = [self.trie]
        found = False
        for v in self.currents:
            if letter in v:
                vv = v[letter]
                found |= \"-\" in vv
                if \"-\" not in vv or len(vv) > 1:
                    keep.append(vv)

        self.currents = keep
        return found

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            root = self.trie
            for w in word:
                if w not in root:
                    root[w] = {}
                root = root[w]
            root['#'] = {}
        self.q = []
            
        

    def query(self, letter: str) -> bool:
        i = 0
        self.q = [p[letter] for p in self.q if letter in p]
        if letter in self.trie:
            self.q.append(self.trie[letter])
        for p in self.q:
            if '#' in p:
                return True
        return False
            

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        # #-means end of word and @-means query pointer
        for word in words:
            cur = self.trie
            for c in word:
                if c not in cur:
                    cur[c] = {}
                cur = cur[c]
            cur[\"#\"] = True
        self.pointers = [self.trie]
        self.ends = set()
        self.waiting = []

    def query(self, letter: str) -> bool:
        
        self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any(\"#\" in node for node in self.waiting)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
    # Simple version
    def __init__(self, words: List[str]):
        self.wait_list = []
        self.trie = dict()

        for w in words:
            temp_dict = self.trie
            for c in w:
                temp_dict = temp_dict.setdefault(c, dict())
            temp_dict['#'] = '#'

    def query(self, letter: str) -> bool:
        new_wait = []
        if letter in self.trie:
            new_wait.append(self.trie[letter])
        for item in self.wait_list:
            if letter in item:
                new_wait.append(item[letter])

        self.wait_list = new_wait
        return any('#' in wait for wait in self.wait_list)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


# class StreamChecker:

#     def __init__(self, words):
#         T = lambda: collections.defaultdict(T)
#         self.trie = T()
#         for w in words: reduce(dict.__getitem__, w[::-1], self.trie)['#'] = True
#         self.S = \"\"
#         self.W = max(map(len, words))

#     def query(self, letter):
#         self.S = (letter + self.S)[:self.W]
#         cur = self.trie
#         for c in self.S:
#             if c in cur:
#                 cur = cur[c]
#                 if cur['#'] == True:
#                     return True
#             else:
#                 break
#         return False

class StreamChecker(object):

    def __init__(self, words):
        \"\"\"
        :type words: List[str]
        \"\"\"      
        self.waitlist = []
        self.trie = {}
        for word in words:
            # create a temporary dict based off our root dict object
            temp_dict = self.trie
            for letter in word:
                # update our temporary dict and add our current letter and a sub-dictionary
                # if key is not in dict, setdefault() will add {key:{}} and return default value {}
                # otherwise it will directly return the existing value of key
                temp_dict = temp_dict.setdefault(letter, dict())
            # If our word is finished, add {'#': '#'} at the stopping node
            temp_dict['#'] = '#'

    def query(self, letter):
        \"\"\"
        :type letter: str
        :rtype: bool
        \"\"\"
        waitlist = []
        # if letter can be the prefix of word
        if letter in self.trie:
            waitlist.append(self.trie[letter])
        # for each possible prefix, append letter if the new substr still can be a prefix
        for item in self.waitlist:
            if letter in item:
                waitlist.append(item[letter])
                
        self.waitlist = waitlist
        return any('#' in item for item in self.waitlist)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Node:
    def __init__(self, val=None):
        self.kids = defaultdict(Node)
        self.val = val
        self.word = False
        
class Trie:
    def __init__(self):
        self.head = Node()
        
    def add(self, word):
        N = len(word)
        curr = self.head
        
        for i in range(N-1, -1, -1):
            c = word[i]
            curr = curr.kids[c]
            
        curr.word = True
    
        
    def search(self, word):
        N = len(word)
        curr = self.head
        
        for i in range(N-1, -1, -1):
            c = word[i]
            if c in curr.kids:
                curr = curr.kids[c]
                if curr.word:
                    return True
            else:
                return False
            
        return curr.word
    
    
            
            
        
    
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.max = 0
        
        for word in words:
            self.trie.add(word)
            self.max = max(self.max, len(word))
        
        self.history = deque()

    def query(self, letter: str) -> bool:
        self.history.append(letter)
        if len(self.history) > self.max:
            self.history.popleft()
            
        out = self.trie.search(self.history)
        print(letter, \"->\", out)
        return out
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:
    def __init__(self, words: List[str]):
        self.trie = {}
        self.nodes = []
        for word in words:
            node = self.trie
            for char in word:
                if char not in node:
                    node[char] = {}
                node = node[char]
            node['end'] = True


    def query(self, letter: str) -> bool:
        self.nodes.append(self.trie)
        res = False
        new_nodes = []
        for node in self.nodes:
            if letter in node:
                node = node[letter]
                if 'end' in node:
                    res = True
                new_nodes.append(node)
        self.nodes = new_nodes     
        return res

class StreamChecker:

    def __init__(self, words: List[str]):
        self.waitlist = []
        self.trie = dict()
        for word in words:
            temp_dict = self.trie
            for letter in word:
                temp_dict = temp_dict.setdefault(letter, dict())
            temp_dict['#'] = '#'
            
    def query(self, letter: str) -> bool:
        waitlist = []
        if letter in self.trie:
            waitlist.append(self.trie[letter])
        for item in self.waitlist:
            if letter in item:
                waitlist.append(item[letter])
                
        self.waitlist = waitlist
        return any('#' in item for item in self.waitlist)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)




class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = {}
        for word in words:
            curr = self.root
            for c in word:
                curr = curr.setdefault(c, {})
            curr['$'] = '$'
        self.stack = [self.root]

    def query(self, letter: str) -> bool:
        stack = []
        flag = False
        for node in self.stack:
            child = node.get(letter)
            if child:
                stack.append(child)
                flag |= '$' in child
        self.stack = stack
        self.stack.append(self.root)
        return flag

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


# class StreamChecker:

#     def __init__(self, words):
#         T = lambda: collections.defaultdict(T)
#         self.trie = T()
#         for w in words: reduce(dict.__getitem__, w[::-1], self.trie)['#'] = True
#         self.S = \"\"
#         self.W = max(map(len, words))

#     def query(self, letter):
#         self.S = (letter + self.S)[:self.W]
#         cur = self.trie
#         for c in self.S:
#             if c in cur:
#                 cur = cur[c]
#                 if cur['#'] == True:
#                     return True
#             else:
#                 break
#         return False

class StreamChecker(object):

    def __init__(self, words):
        \"\"\"
        :type words: List[str]
        \"\"\"      
        self.waitlist = []
        self.trie = dict()
        for word in words:
            # create a temporary dict based off our root dict object
            temp_dict = self.trie
            for letter in word:
                # update our temporary dict and add our current letter and a sub-dictionary
                # if key is not in dict, setdefault() will add {key:{}} and return default value {}
                # otherwise it will directly return the existing value of key
                temp_dict = temp_dict.setdefault(letter, dict())
            # If our word is finished, add {'#': '#'} at the stopping node
            temp_dict['#'] = '#'

    def query(self, letter):
        \"\"\"
        :type letter: str
        :rtype: bool
        \"\"\"
        waitlist = []
        # if letter can be the prefix of word
        if letter in self.trie:
            waitlist.append(self.trie[letter])
        # for each possible prefix, append letter if the new substr still can be a prefix
        for item in self.waitlist:
            if letter in item:
                waitlist.append(item[letter])
                
        self.waitlist = waitlist
        return any('#' in item for item in self.waitlist)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Node:
    def __init__(self):
        self.children = {}
        self.isWord = False

class Trie:

    def __init__(self):
        self.root = Node()

    def add(self, word):
        cur = self.root
        for ch in word:
            if ch not in cur.children:
                cur.children[ch] = Node()
            cur = cur.children[ch]
        cur.isWord = True

    def check(self, word):
        cur = self.root
        for ch in word:
            if cur.isWord:
                return True
            if ch not in cur.children:
                return False
            cur = cur.children[ch]
        return cur.isWord



class StreamChecker:

    def __init__(self, words: List[str]):
        self.T = Trie()
        for word in words:
            self.T.add(word[::-1])
        self.arr = []
        

    def query(self, letter: str) -> bool:
        self.arr.append(letter)
        return self.T.check(self.arr[::-1])

        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        dic = {}
        for w in words:
            p = dic
            for c in w:
                if c not in p: p[c] = {}
                p = p[c]
            p['#'] = True
        self.dic = dic
        self.cur = []

    def query(self, letter: str) -> bool:
        tmp, self.cur = self.cur, []
        tmp.append(self.dic)
        res = False
        for d in tmp:
            if letter in d:
                self.cur.append(d[letter])
                if '#' in d[letter]:
                    res = True
        return res

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker(object):

    def __init__(self, word):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in word: reduce(dict.__getitem__, w, self.trie)['#'] = True
        self.waiting = []

    def query(self, letter):
        self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any(\"#\" in node for node in self.waiting)



    
class StreamChecker:

    
    def __init__(self, words: List[str]):
        self.Trie={'chld':{},'end':False}
        
        for word in words:
            T=self.Trie
            for l in reversed(word):
                if l not in T['chld']:
                    T['chld'][l]={'chld':{},'end':False}
                T=T['chld'][l]
                
            T['end']=True
            
        self.stack=''
        
        

    def query(self, letter: str) -> bool:
        
        self.stack+=letter
        
        T=self.Trie
        for i in range(len(self.stack)-1,-1,-1):
            l=self.stack[i]
            if l not in T['chld']:
                #print (letter)
                return False
            T=T['chld'][l]
            if T['end']:
               # print(l,letter)
                return True
        
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = self.buildTrie(words)
        self.waitlist = [] # queue
        
        
    def buildTrie(self, words):
        trie = {}
        for word in words:
            curr = trie
            for ch in word:
                curr = curr.setdefault(ch, {})
            curr[\"#\"] = \"#\"
        return trie
        
        
    def query(self, letter: str) -> bool:
        waitlist = []
        
        # check if letter is at the root 
        if letter in self.trie:
            waitlist.append(self.trie[letter])
            
        for item in self.waitlist:
            if letter in item:
                waitlist.append(item[letter])
            
        self.waitlist = waitlist
        return any(\"#\" in item for item in self.waitlist)

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:
#??????????????????????????????????
    def __init__(self, words: List[str]):
        self.waitlist=[]
        self.trie=dict()
        for w in words:
            temp_dict=self.trie
            for letter in w:
                #if key is not in dict, setdefault() will add {key:{}} and return default value {}
                # otherwise it will directly return the existing value of key
                temp_dict=temp_dict.setdefault(letter,dict())
            temp_dict['#']='#'
            

    def query(self, letter: str) -> bool:
        waitlist=[]
        if letter in self.trie:
            waitlist.append(self.trie[letter])
        for item in self.waitlist:
            if letter in item:
                waitlist.append(item[letter])
        self.waitlist=waitlist
        return any('#' in item for item in self.waitlist)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.words = words
        self.history = ''
        self.trie = {}
        for w in words:
            p = self.trie
            for c in w:
                if c not in p: p[c] = {}
                p = p[c]
            p['#'] = w
        self.p = [self.trie]

    def query(self, letter: str) -> bool:
        self.history+=letter
        self.p = [p[letter] for p in self.p if letter in p]
        res = any(['#' in p for p in self.p])
        self.p+=[self.trie]
        return res

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.waitlist = []
        for word in words:
            head = self.trie
            for char in word:
                if char not in head:
                    head[char] = {}
                head = head[char]
            head['#'] = '#'

    def query(self, letter: str) -> bool:
        waitlist = []
        # if letter can be the prefix of word
        if letter in self.trie:
            waitlist.append(self.trie[letter])
        # for each possible prefix, append letter if the new substr still can be a prefix
        for item in self.waitlist:
            if letter in item:
                waitlist.append(item[letter])
                
        self.waitlist = waitlist
        return any('#' in item for item in self.waitlist)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter) 


class StreamChecker:

    def __init__(self, words: List[str]):
        self.dictionary={}
        for word in words:
            current=self.dictionary
            for letter in word:
                if letter not in current:
                    current[letter]={}
                current=current[letter]
            current['!']={}
        self.memory=[]

    def query(self, letter: str) -> bool:
        memory=self.memory+[self.dictionary]
        self.memory=[]
        validity=False
        for entry in memory:
            if letter in entry:
                self.memory.append(entry[letter])
                if '!' in entry[letter]:
                    validity=True
        return validity


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


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

class StreamChecker:

    def __init__(self, words: List[str]):
        self.head = TrieNode()
        for word in words:
            p = self.head
            for c in word:
                p = p.children[c]
            p.isWord = True
        self.pos = [self.head]
        
    def query(self, letter: str) -> bool:
        tmp = [self.head]
        is_word = False
        for p in self.pos:
            if letter in p.children:
                nxt = p.children[letter]
                tmp.append(nxt)
                if nxt.isWord:
                    is_word = True
        self.pos = tmp
        return is_word


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        _compress = {}
        _decompress = {}
        def compress(s):
            if s not in _compress:
                i = len(_compress)
                _compress[s] = i
                _decompress[i] = s                
            return _compress[s]
        def decompress(i):
            return _decompress[i]
        compress('')
        
        words = set(words)
        graph = defaultdict(lambda: defaultdict(int)) # pref1 -> ch -> pref2 where pref2 is longest word that is a suffix of pref1
        prefs = set()
        for word in words:
            for i in range(len(word) + 1):
                pref = word[:i]
                prefs.add(pref)
        
        for pref in prefs:
            for i in range(26):
                ch = chr(ord('a') + i)
                for j in range(len(pref) + 1):
                    pref2 = pref[j:] + ch
                    if pref2 in prefs and len(pref2) > len(decompress(graph[compress(pref)][ch])):
                        graph[compress(pref)][ch] = compress(pref2)
                
        prefWithWordSuffix = set()
        for pref in prefs:
            for i in range(len(word) + 1):
                if pref[i:] in words:
                    prefWithWordSuffix.add(compress(pref))
                    break
        self.graph = graph
        self.state = compress('')
        self.prefWithWordSuffix = prefWithWordSuffix
        # self.compress = compress
        # self.decompress = decompress

    def query(self, letter: str) -> bool:
        
        self.state = self.graph[self.state][letter]
        
        
        return self.state in self.prefWithWordSuffix
        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            node = self.trie
            for c in word:
                if c not in node:                    
                    node[c] = {}
                node = node[c]
            node['$'] = word
        self.states = [self.trie]
    def query(self, letter: str) -> bool:
        nextStates = [self.trie]
        for state in self.states:
            if letter in state:
                nextStates.append(state[letter])
        self.states = nextStates
        #print(letter, [state['$'] for state in self.states if '$' in state])
        return any('$' in state for state in self.states)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = trie = {}
        for word in words:
            node = trie
            for letter in word:
                node = node.setdefault(letter, {})
            node['end'] = True
        self.s = []
    def query(self, letter: str) -> bool:
        f = 0
        temp = []
        self.s.append(self.trie)
        for d in self.s:
            if letter in d:
                t = d[letter]
                f |= 'end' in t
                temp.append(t)
        self.s = temp
        return f
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


MAX_WORD_LEN = 2000

class StreamChecker:
    def __init__(self, words: List[str]):
        self.ring_buffer = [None] * MAX_WORD_LEN
        self.index = 0
        self.words = set(words)
        self.possible_chars = set([
            char for word in self.words for char in word
        ])

    def query(self, letter: str) -> bool:
        self.add_letter(letter)
        if letter not in self.possible_chars:
            return False
        
        for word in self.words:
            if word[-1] != letter:
                continue
            if self.endswith(word):
                return True
        return False
    
    def add_letter(self, letter):
        self.ring_buffer[self.index] = letter
        self.index = (self.index + 1) % MAX_WORD_LEN
        
    def endswith(self, word):
        index = (self.index - len(word)) % MAX_WORD_LEN
        for i in range(len(word)):
            if self.ring_buffer[index] != word[i]:
                return False
            index = (index + 1) % MAX_WORD_LEN
        return True

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.waitlist = []
        self.trie = dict()
        
        for word in words:
            temp_dict = self.trie
            for letter in word:
                temp_dict = temp_dict.setdefault(letter, dict())
            temp_dict['#'] = '#'
            
        

    def query(self, letter: str) -> bool:
        waitlist = []
        if letter in self.trie:
            waitlist.append(self.trie[letter])
        for item in self.waitlist:
            if letter in item:
                waitlist.append(item[letter])
        self.waitlist = waitlist
        return any('#' in item for item in self.waitlist)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from collections import deque


class Node:

    def __init__(self):
        self.children = dict()
        self.isEnd = False
        self.word = \"\"


class Trie:

    def __init__(self):
        self.root = Node()
        

    def insert(self, word):
        current = self.root

        for i in range(len(word)):
            if current.children.get(word[i], None) is None:
                current.children[word[i]] = Node()
            current = current.children[word[i]]
        current.isEnd = True
        current.word = word

    # def query(self, letter):
        

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.q = deque()
        for word in words:
            self.trie.insert(word[::-1])

        

    def query(self, letter: str) -> bool:
        self.q.appendleft(letter)
        current = self.trie.root

        for c in self.q:
            if c in current.children:
                current = current.children[c]
                if current.isEnd:
                    return True
            else:
                return False
        return False


        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        trie = {}
        for word in words:
            ptr = trie
            for c in word:
                if c not in ptr:
                    ptr[c] = {}
                ptr = ptr[c]
            ptr[\"term\"] = True
        self.trie = trie
        self.curr = []
                
    def query(self, letter: str) -> bool:
        # add new start
        self.curr.append(self.trie)
        # progress
        new_curr = []
        res = False
        for ptr in self.curr:
            if letter in ptr:
                ptr = ptr[letter]
                if not res and ptr.get(\"term\", False):
                    res = True
                new_curr.append(ptr)
        self.curr = new_curr
        return res


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in words: reduce(dict.__getitem__, w, self.trie)['#'] = True
        self.waiting = []

    def query(self, letter):
        self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any(\"#\" in node for node in self.waiting)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.waitlist = []
        self.trie = dict()
        for word in words:
            # create a temporary dict based off our root dict object
            temp_dict = self.trie
            for letter in word:
                # update our temporary dict and add our current letter and a sub-dictionary
                # if key is not in dict, setdefault() will add {key:{}} and return default value {}
                # otherwise it will directly return the existing value of key
                temp_dict = temp_dict.setdefault(letter, dict())
            # If our word is finished, add {'#': '#'} at the stopping node
            temp_dict['#'] = '#'

    def query(self, letter: str) -> bool:
        waitlist = []
        # if letter can be the prefix of word
        if letter in self.trie:
            waitlist.append(self.trie[letter])
        # for each possible prefix, append letter if the new substr still can be a prefix
        for item in self.waitlist:
            if letter in item:
                waitlist.append(item[letter])
                
        self.waitlist = waitlist
        return any('#' in item for item in self.waitlist)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self, end=False):
        self.next = {}
        self.end = False
    
class StreamChecker:

    def __init__(self, words):
        \"\"\"
        :type words: List[str]
        \"\"\"      
        self.waitlist = []
        self.trie = dict()
        for word in words:
            # create a temporary dict based off our root dict object
            temp_dict = self.trie
            for letter in word:
                # update our temporary dict and add our current letter and a sub-dictionary
                # if key is not in dict, setdefault() will add {key:{}} and return default value {}
                # otherwise it will directly return the existing value of key
                temp_dict = temp_dict.setdefault(letter, dict())
            # If our word is finished, add {'#': '#'} at the stopping node
            temp_dict['#'] = '#'

    def query(self, letter):
        \"\"\"
        :type letter: str
        :rtype: bool
        \"\"\"
        waitlist = []
        # if letter can be the prefix of word
        if letter in self.trie:
            waitlist.append(self.trie[letter])
        # for each possible prefix, append letter if the new substr still can be a prefix
        for item in self.waitlist:
            if letter in item:
                waitlist.append(item[letter])
                
        self.waitlist = waitlist
        return any('#' in item for item in self.waitlist)

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.d = {}
        for w in words:
            c = self.d
            i = 0
            while i < len(w):
                if w[i] not in c:
                    c[w[i]] = {}
                c = c[w[i]]
                i += 1
            c[''] = True
        self.ps = []

    def query(self, letter: str) -> bool:
        nps = []
        for p in self.ps+[self.d]:
            if letter in p:
                nps.append(p[letter])
        self.ps = nps
        return any('' in p for p in self.ps)

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in words: functools.reduce(dict.__getitem__, w, self.trie)['#'] = True
        self.waiting = []

    def query(self, letter):
        self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any(\"#\" in node for node in self.waiting)
            
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.t = {}
        for word in words:
            curr = self.t
            for c in word:
                if c not in curr:
                    curr[c] = {}
                curr = curr[c]
            curr[''] = None
            
        self.cursor = []
        
    def query(self, letter: str) -> bool:
        self.cursor = [x[letter] for x in self.cursor if letter in x]
        if letter in self.t:
            self.cursor.append(self.t[letter])
        for c in self.cursor:
            if '' in c:
                return True
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = {}
        for word in words:
            t = self.root
            for c in word:
                if c not in t: t[c] = {}
                t = t[c]
            t['end'] = True
        self.temp = [self.root]

    def query(self, letter: str) -> bool:
        nextTemp = []
        flag = False
        for node in self.temp:
            if letter not in node:
                continue
            node = node[letter]
            nextTemp.append(node)
            if 'end' in node:
                flag = True
        nextTemp += [self.root]
        self.temp = nextTemp
        return flag


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in words: 
            reduce(dict.__getitem__, w, self.trie)['#'] = True
        self.waiting = []

    def query(self, letter: str) -> bool:
        self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any(\"#\" in node for node in self.waiting)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

# 题目要求按从旧到新顺序查询，因此可以将从旧到新的 query 存起来形成一个单词 stream。

# 比如：

# streamChecker.query(\"a\"); // stream： a
# streamChecker.query(\"b\"); // stream：ba
# streamChecker.query(\"c\"); // stream：cba
# 这里有两个小的点需要注意：

# 如果用数组来存储， 由于每次都往数组头部插入一个元素，因此每次 query 操作的时间复杂度为 $O(N)$，其中 $N$ 为截止当前执行 query 的次数，我们可以使用双端队列进行优化。
# 由于不必 query 形成的查询全部命中。比如 stream 为 cba 的时候，找到单词 c， bc， abc 都是可以的。如果是找到 c，cb，cba 比较好吧，现在是反的。其实我们可以反序插入是，类似的技巧在211.add-and-search-word-data-structure-design 也有用到。
# 之后我们用拼接的单词在 words 中查询即可， 最简单的方式当然是每次 query 都去扫描一次，这种方式毫无疑问会超时。

# 我们可以采用构建 Trie 的形式，即已空间环时间， 其代码和常规的 Trie 类似，只需要将 search(word) 函数做一个简单修改即可，我们不需要检查整个 word 是否存在， 而已 word 的前缀存在即可。

# 提示：可以通过对 words 去重，来用空间换区时间。

# 具体算法：

# init 中 构建 Trie 和 双端队列 stream
# query 时，往 stream 的左边 append 即可。
# 调用 Trie 的 search（和常规的 search 稍有不同， 我上面已经讲了）
# 核心代码（Python）：

# class StreamChecker:

#     def __init__(self, words: List[str]):
#         self.trie = Trie()
#         self.stream = deque([])

#         for word in set(words):
#             self.trie.insert(word[::-1])

#     def query(self, letter: str) -> bool:
#         self.stream.appendleft(letter)
#         return self.trie.search(self.stream)

# 关键点解析
# 前缀树模板
# 倒序插入




class Trie:

    def __init__(self):
        \"\"\"
        Initialize your data structure here.
        \"\"\"
        self.Trie = {}

    def insert(self, word):
        \"\"\"
        Inserts a word into the trie.
        :type word: str
        :rtype: void
        \"\"\"
        curr = self.Trie
        for w in word:
            if w not in curr:
                curr[w] = {}
            curr = curr[w]
        curr['#'] = 1

    def search(self, word):
        \"\"\"
        Returns if the word is in the trie.
        :type word: str
        :rtype: bool
        \"\"\"
        curr = self.Trie
        for w in word:
            if w not in curr:
                return False
            if \"#\" in curr[w]:
                return True
            curr = curr[w]
        return False


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.stream = deque([])

        for word in set(words):
            self.trie.insert(word[::-1])   #反向插入

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        return self.trie.search(self.stream)


class Trie:
    
    def __init__(self):
        self.root = {}
        self.curr = self.root
    
    def add(self, word):
        node = self.root
        for char in word:
            if char not in node:
                node[char] = {}
            node = node[char]
        node['.'] = True
        
    def search(self, char):
        node = self.curr
        if char in node:
            node = node[char]
            self.curr = node
            return '.' in node
        else:
            self.curr = self.root
            return False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.stream = deque()
        self.trie = Trie()
        for w in words:
            self.trie.add(w[::-1])

    def query(self, letter: str) -> bool:
        self.stream.appendleft(letter)
        node = self.trie.root
        for char in self.stream:
            if char in node:
                node = node[char]
                if '.' in node:
                    return True
            else:
                break
        return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)
'''
[[[\"ab\",\"ba\",\"aaab\",\"abab\",\"baa\"]],
[\"a\"],[\"a\"],[\"a\"],[\"a\"],[\"a\"],[\"b\"],[\"a\"],
  F     F     F     F     F     T     T
'''

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for w in words:
            node = self.trie
            for char in w:
                node.setdefault(char,{})
                node = node[char]
            node.setdefault('*',{})
        self.curr = [self.trie]

    def query(self, letter: str) -> bool:
        new_curr = [self.trie]
        ret = False
        for node in self.curr:
            if letter in node:
                node = node[letter]
                new_curr.append(node)
                if '*' in node:
                    ret = True
        self.curr = new_curr
        return ret


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self, char, isTerminal):
        self.char = char
        self.isTerminal = isTerminal
        self.nei = {}


class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = TrieNode(\"\", False)
        list(map(lambda x : self.insert(x[::-1], self.root),words ))
        self.q = \"\"
    def insert(self, word, root):
        if len(word) == 0:
            self.root.Isterminal = True
            return
        isTerminal = len(word)==1
        if word[0] in root.nei:
            root.nei[word[0]].isTerminal |= isTerminal
        else:
            child = TrieNode(word[0], isTerminal)
            root.nei[word[0]] = child
            
        if not isTerminal:
            self.insert(word[1:], root.nei[word[0]])

    def prinT(self, root, path):
        if root.isTerminal:
            print(path)
        for nei in root.nei:
            self.prinT( root.nei[nei], path[:] + root.nei[nei].char)
            
    def search(self, root, word):
        if not word:
            return root.isTerminal
        if root.isTerminal:
            return True
        
        if word[0] in root.nei:
            return self.search(root.nei[word[0]], word[1:])
        else:
            return False
        
    def query(self, letter: str) -> bool:
        self.q += letter
 
        
        if self.search(self.root, self.q[::-1]):
            return True
            
        return False
                
        # q = self.q
        # while q:
        #     print(q)
        #     if self.search(self.root, q):
        #         break
        #     q = q[1:]
        # self.q = q
        return len(self.q) >= 1 


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = dict()
        self.pointers = list()
        for word in words:
            node = self.trie
            for c in word:
                node = node.setdefault(c, {})
            
            node[\"#\"] = True
    
    def query(self, letter: str) -> bool:
        res = False
        self.pointers = [node[letter] for node in self.pointers if letter in node]
        res = res or any(\"#\" in node for node in self.pointers)
        
        if letter in self.trie:
            node = self.trie[letter]
            res = res or (\"#\" in node)
            self.pointers.append(node)
        
        return res

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for w in words:
            lastC = self.trie
            for c in w:
                lastC[c] = lastC.get(c, {})
                lastC = lastC[c]
            lastC['*'] = True
        self.words = []
        

    def query(self, letter: str) -> bool:
        newWords = []
        if letter in self.trie:
            newWords.append(self.trie[letter])
        for t in self.words:
            if letter in t:
                newWords.append(t[letter])
        self.words = newWords
        return any(['*' in t for t in self.words])


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
# with the trie like #ba and baa 
# before my solution when it fit ba, it will set the curr the self.trie['a'] again, which will miss the potential of baa， need a structure to preserve all possible curr

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            curr = self.trie
            for char in word:
                if char not in curr:
                    curr[char] = {}
                curr = curr[char]
            curr['#'] = 1
        #self.curr = self.trie
        self.tmp = [self.trie]


    def query(self, letter: str) -> bool:
        new_tmp = [self.trie]
        flag = False
        for curr in self.tmp:
            if letter in curr:
                curr = curr[letter]
                new_tmp.append(curr)
                #check if it's the end
                if '#' in curr: 
                    flag = True
                    if letter in self.trie:
                        new_tmp.append(self.trie[letter])      

            #else:
                #self.curr = self.trie
            #    new_tmp.append(self.trie)
        self.tmp = new_tmp

        return flag


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)






class StreamChecker:
    
    def __init__(self, words: List[str]):
        
        self.queries = []
        trie = {}
        for word in words:
            word = list(reversed(word))
            here = trie
            for i in range(len(word)):
                if word[i] not in list(here.keys()):
                    here[word[i]] = {}
                here = here[word[i]]
            here['is_word'] = True
            
        self.trie = trie    
                

    def query(self, letter: str) -> bool:
        self.queries.append(letter)
        
        here = self.trie
        for i in range(1, len(self.queries) + 1):
            if self.queries[-i] not in list(here.keys()):
                return False
            here = here[self.queries[-i]]
            if 'is_word' in list(here.keys()):
                return True
        
        
            
        # for i in range(1, min(len(self.queries), self.max_len) + 1):
        #     if i in self.vocab.keys():
        #         word = \"\".join(self.queries[-i:])
        #         if word in self.vocab[i]:
        #             return True
        # return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words):
        \"\"\"
        :type words: List[str]
        \"\"\"      
        self.waitlist = []
        self.trie = dict()
        for word in words:
            # create a temporary dict based off our root dict object
            temp_dict = self.trie
            for letter in word:
                # update our temporary dict and add our current letter and a sub-dictionary
                # if key is not in dict, setdefault() will add {key:{}} and return default value {}
                # otherwise it will directly return the existing value of key
                temp_dict = temp_dict.setdefault(letter, dict())
            # If our word is finished, add {'#': '#'} at the stopping node
            temp_dict['#'] = '#'

    def query(self, letter):
        \"\"\"
        :type letter: str
        :rtype: bool
        \"\"\"
        waitlist = []
        # if letter can be the prefix of word
        if letter in self.trie:
            waitlist.append(self.trie[letter])
        # for each possible prefix, append letter if the new substr still can be a prefix
        for item in self.waitlist:
            if letter in item:
                waitlist.append(item[letter])
                
        self.waitlist = waitlist
        return any('#' in item for item in self.waitlist)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for w in words:
            start = self.trie
            for i, l in enumerate(w):
                if l not in start:
                    start[l] = {}
                start = start[l]
            start['#'] = True
        self.past = [self.trie]
    def query(self, letter: str) -> bool:
        ans = False
        new_past = [self.trie]
        for ele in self.past:
            if letter in ele:
                if '#' in ele[letter]:
                    ans = True
                new_past.append(ele[letter])
        self.past = new_past
        return ans
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
    
    def build_trie(self, word: str) -> None:
        place = self.trie
        for ch in word:
            if ch in place:
                place = place[ch]
            else:
                place[ch] = dict()
                place = place[ch]
        place['*'] = None
    
    def __init__(self, words: List[str]) -> None:
        self.words = set(words)
        self.trie = dict()
        for word in words:
            self.build_trie(word)
        print((self.trie))
        self.temp = []
        self.temp2 = []

    def query(self, letter: str) -> bool:
        self.temp2 = []
        self.temp.append(self.trie)
        can = False
        for i in self.temp:
            if letter in i:
                self.temp2.append(i[letter])
                if '*' in i[letter]:
                    can = True
            else:
                continue
        self.temp = self.temp2
        return can
            


class StreamChecker:
    STOP_CHAR = \"\
\"
    
    def __init__(self, words: List[str]):
        self.root = dict()
        self.pointers = list()
        for word in words:
            self.add(word)

    def add(self, word):
        word += self.STOP_CHAR
        root = self.root
        for char in word:
            if char not in root:
                root[char] = dict()
            
            root = root[char]
    
    def query(self, letter: str) -> bool:
        self.pointers = [
            pointer[letter]
            for pointer in self.pointers
            if pointer.get(letter) is not None
        ]
        new_pointer = self.root.get(letter)
        if new_pointer is not None:
            self.pointers.append(new_pointer)
        for pointer in self.pointers:
            if self.STOP_CHAR in pointer:
                return True
        return False
    
    
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            cur = self.trie
            for c in word:
                if c not in cur:
                    cur[c] = {}
                cur = cur[c]
            cur[\"-\"] = True
        self.currents = [self.trie]
        #print(self.trie[\"b\"])

    def query(self, letter: str) -> bool:
        keep = [self.trie]
        found = False
        for v in self.currents:
            if letter in v:
                vv = v[letter]
                found |= \"-\" in vv
                if \"-\" not in vv or len(vv) > 1:
                    keep.append(vv)

        self.currents = keep
        return found
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        
        for word in words:
            current = self.trie
            for letter in word:
                current.setdefault(letter, {})
                current = current[letter]
            current[\"__end__\"] = word
        
        self.currents = []
    def query(self, letter: str) -> bool:
        
        self.currents.append(self.trie)
        
        ans = False
        new_currents = []
        for pos, current in enumerate(self.currents):
            if letter in current:
                new_currents.append(current[letter])
                if \"__end__\" in current[letter]:
                    ans = True
        self.currents = new_currents
        return ans

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

_end = '_end'

def make_trie(words):
    root = dict()
    for word in words:
        current_dict = root
        for letter in word:
            current_dict = current_dict.setdefault(letter, {})
        current_dict[_end] = _end
    return root

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = make_trie(words)
        self.cur_tries = []

    def query(self, letter: str) -> bool:
        new_tries = []
        result = False
        for tr in self.cur_tries + [self.trie]:
            if letter in tr:
                if _end in tr[letter]:
                    result = True
                if _end not in tr[letter] or len(tr[letter]) > 1:
                    new_tries.append(tr[letter])
        self.cur_tries = new_tries   
        
        return result
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.words = set(words)
        self.query_history = \"\"
        self.max_word_len = max(map(len, words))

    def query(self, letter: str) -> bool:
        self.query_history = self.query_history[-self.max_word_len + 1:] + letter
        return any(self.query_history.endswith(word) for word in self.words)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker(object):

    def __init__(self, words):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in words: reduce(dict.__getitem__, w, self.trie)['#'] = True
        self.waiting = []

    def query(self, letter):
        self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any(\"#\" in node for node in self.waiting)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:
    
    def __init__(self, words: List[str]):
        
        self.trie = {}
        
        for word in words:
            cur = self.trie
            for c in word:
                if c not in cur:
                    cur[c] = {}
                cur = cur[c]
            cur['end'] = None  
            
        self.buffer = []
        
    def query(self, letter: str) -> bool:
        
        found = False
        swap = []
        if letter in self.trie:
            swap.append(self.trie[letter])
            found = 'end' in self.trie[letter]

        for b in self.buffer:
            if letter in b:
                swap.append(b[letter])
                if 'end' in b[letter]:
                    found = True
        self.buffer = swap
        return found


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Node:
    def __init__(self, v=None):
        self.children: Dict[str, Node] = {}
        self.parent: Node
        self.value = v
    
class Trie:
    def __init__(self):
        self.t = Node() #root;
        self.leaves: Dict[str, List[Node]] = {}
        self.maxLen: int = 0

    def addLeave(self, w:str, n:Node) -> None:
        if w not in list(self.leaves.keys()):
            self.leaves[w] = []
        self.leaves[w].append(n)
        
    def insert(self, w: str) -> None:
        self.maxLen = max(self.maxLen, len(w))
        tl = self.t
        j = 0
        while j<len(w):
            i = w[j]
            n = tl.children.get(i, None)
            if n != None: #this char exist
                tl = n
                j += 1
            else:
                for i in w[j:]:
                    newNode = Node(i)
                    newNode.parent = tl
                    tl.children[i] = newNode
                    tl = newNode
                break
        self.addLeave(tl.value, tl)

    

class StreamChecker:
    from collections import deque
    
    def __init__(self, words: List[str]):
        self.trie = Trie()
        [self.trie.insert(w) for w in words]
        self.q = deque(maxlen = self.trie.maxLen)

    
    def check_leaves(self) -> None:
        for s in self.trie.leaves:
            for i in self.trie.leaves[s]: #leave node
                j = i
                l=0
                while j.parent.value != None:
                    j = j.parent
                    l += 1
                print((s, l))
                
    def query(self, letter: str) -> bool:
        self.q.append(letter)
        fl = self.trie.leaves.get(letter, None)
        if fl==None:
            return False
        
        #print(\"last str\", letter)
        for f in fl:
            i = len(self.q) -2
            #print(\"try\")
            if f.parent.value==None: #reached root
                return True #already reach
            while i>=0:
                l = self.q[i]
                #print(l, f.parent.value)
                if f.parent.value == l:
                    f = f.parent
                    i -= 1
                else:
                    break
                
                if f.parent.value==None: #reached root
                    return True #already reach

        return False
                
            
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.pointers = []
        for w in words:
            t = self.trie
            for c in w:
                if c not in t:
                    t[c] = {}
                t = t[c]
            t['*'] = '*'        

    def query(self, letter: str) -> bool:
        new_ptr = self.trie
        self.pointers.append(new_ptr)
        new_pointers = []
        ret_val = False
        for p in self.pointers:
            if letter in p:
                p = p[letter]
                if '*' in p:
                    ret_val = True
                new_pointers.append(p)
        self.pointers = new_pointers
        return ret_val


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    
    def __init__(self):
        self.children = {}
        self.is_word = False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = self.build(words)
        self.history = []

    def query(self, letter: str) -> bool:
        self.history.append(self.root)
        tmp = [node.children[letter] for node in self.history if letter in node.children]
        self.history = tmp
        for node in tmp:
            if node.is_word:
                return True
        return False

    def build(self, words):
        root = TrieNode()
        for word in words:
            tmp = root
            for c in word:
                if c not in tmp.children:
                    tmp.children[c] = TrieNode()
                tmp = tmp.children[c]
            tmp.is_word = True
        return root

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.letters = ''
        self.words = words
        self.max_length = max([len(x) for x in words])

    def query(self, letter: str) -> bool:
        self.letters += letter
        self.letters = self.letters[-self.max_length:]
        # print(letter)
        for word in self.words:
            if word[-1] != letter:
                continue
            letters_word = self.letters[-len(word):]
            # print(f'{word} == {letters_word} ??')
            if word == letters_word:
                # print(True, word)
                return True
        # print(False)
        return False



# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            root = self.trie
            for ch in word:
                if not ch in root:
                    root[ch] = {}
                root = root[ch]
            root['#'] = '#'
            
        self.nodes = [self.trie]

    def query(self, letter: str) -> bool:
        new_nodes = [self.trie]
        res = False
        for node in self.nodes:
            if letter in node:
                new_node = node[letter]
                if '#' in new_node:
                    res = True
                new_nodes.append(new_node)
        self.nodes = new_nodes
        return res
            
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.dict_tree = {}
        for i in words:
            cur = self.dict_tree
            for j in i:
                if j not in cur:
                    cur[j] = {}
                cur = cur[j]
            cur[-1] = True
        self.char_stream = []
        self.to_check = []
                

    def query(self, letter: str) -> bool:
        temp = []
        find = False
        for i in self.to_check:
            if letter in i:
                i = i[letter]
                temp.append(i)
                if -1 in i:
                    find = True
        if letter in self.dict_tree:
            if -1 in self.dict_tree[letter]:
                find = True
            temp.append(self.dict_tree[letter])
        self.to_check = temp
        return True if find else False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


from typing import Dict

class Node:
    def __init__(self, char=None):
        self.char = char
        self.is_complete_word = False
        self.children: Dict[str, 'Node'] = dict()

class Trie:
    def __init__(self):
        self.root = Node()
        
    def insert(self, word: str):
        current = self.root
        for char in word:
            if char not in current.children:
                current.children[char] = Node(char)
            current = current.children[char]
        current.is_complete_word = True

class StreamChecker:
    def __init__(self, words: List[str]):
        self.waitlist = []
        self._max_length = 0
        self.trie = Trie()
        for word in words:
            self.trie.insert(word[::-1])
            self._max_length = max(self._max_length, len(word))

    def query(self, letter: str) -> bool:
        self.waitlist.append(letter)
        i = len(self.waitlist) - 1
        node = self.trie.root
        while i >= 0:
            if node.is_complete_word:
                return True
            letter = self.waitlist[i]
            if letter not in node.children:
                return False
            node = node.children[letter]
            i -= 1
        return node.is_complete_word
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = TrieNode()
        self.waiting = []
        for word in words: 
            self.root.insert(word)
        
        
    def query(self, letter: str) -> bool:
        
        self.waiting = [node.child[letter] for node in self.waiting + [self.root] if letter in node.child]
        
        
        for node in self.waiting:
            if node.is_complete:
                return True
        
        return False
            

class TrieNode:
    def __init__(self):
        self.child = {}
        self.is_complete = False
        
    def insert(self,word): 
        node = self
        for letter in word:
            if letter not in node.child:
                new_node = TrieNode()
                node.child[letter] = new_node
            node = node.child[letter]
        node.is_complete = True
        
    
        
        
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self, end=False):
        self.end = end
        self.lnk = {}
    
class StreamChecker:
    def __init__(self, words: List[str]):
        self.head = TrieNode()
        for w in words:
            x = self.head
            for i, c in enumerate(w):
                if c not in x.lnk:
                    y = TrieNode()
                    x.lnk[c] = y
                x = x.lnk[c]
            x.end = True
        self.ptrs = []

    def query(self, letter: str) -> bool:
        self.ptrs.append(self.head)
        found = False
        new_ptrs = []
        for p in self.ptrs:
            if letter in p.lnk:
                q = p.lnk[letter]
                new_ptrs.append(q)
                found |= q.end
        self.ptrs = new_ptrs
        return found

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    def __init__(self):
        self.children = defaultdict(bool)
    def insert(self,word):
        if word == '':
            self.children['@'] = True
        else:
            child = self.children[word[0]]
            if child:
                child.insert(word[1:])
            else:
                newChild = Trie()
                newChild.insert(word[1:])
                self.children[word[0]] = newChild
                
class StreamChecker:
    def __init__(self, words: List[str]):
        self.root = Trie()
        for word in words:
            self.root.insert(word)
        self.pointers = []

    def query(self, letter: str) -> bool:
        newPointers = []
        retFlag = False
        if letter in self.root.children:
            newPointers.append(self.root.children[letter])
            if '@' in self.root.children[letter].children:
                retFlag = True
        for p in self.pointers:
            newP = p.children[letter]
            if newP:
                newPointers.append(newP)
                if '@' in newP.children:
                    retFlag = True
        self.pointers = newPointers
        return retFlag

class StreamChecker:

    def construct_trie(self, word_list):
        root = dict()
        for word in word_list:
            word += \"_\"
            level = root
            for letter in word:
                if letter not in level:
                    level[letter] = dict()
                level = level[letter]
        return root
    
    def __init__(self, words: List[str]):
        self.liste = self.construct_trie(words)
        self.p = [self.liste]
        

    def query(self, letter: str) -> bool:
        ll = [self.liste]
        b = False
        for dic in self.p:
            if letter in dic:
                d = dic[letter]
                if \"_\" in d:
                    b = True
                ll.append(d)
        self.p = ll
        return b

class StreamChecker:
    # Approach: store reversed words in Trie
    
    def __init__(self, words: List[str]):
        self.stream = []
        self.trie = {}
        for word in words:
            node = self.trie
            for char in reversed(word):
                if char not in node:
                    node[char] = {}
                node = node[char]
            node['EOW'] = word

    def query(self, letter: str) -> bool:
        self.stream = [letter] + self.stream
        node = self.trie
        for char in self.stream:
            if 'EOW' in node:
                return True
            if char not in node:
                return False
            node = node[char]
        return 'EOW' in node


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
    def __init__(self, words: List[str]):
        self.wordict = {}
        self.word = ''
        for word in words:
            node = self.wordict
            for c in word[::-1]:
                if c not in node:
                    node[c] = {}
                node = node[c]
            node[0] = 0

    def query(self, letter: str) -> bool:
        self.word = self.word + letter
        n = len(self.word)
        nodes = self.wordict
        while n:
            if self.word[n-1] in nodes:
                if 0 in nodes[self.word[n-1]]:
                    return True
                else:
                    nodes = nodes[self.word[n-1]]
                    n -= 1
            else:
                return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = dict()
        for word in words:
            node = self.trie
            for c in word[::-1]:
                if c not in node:
                    node[c] = dict()
                node = node[c]
            node['.'] = '.'

        self.syms = []

    def query(self, letter: str) -> bool:
        trie, syms = self.trie, self.syms
        
        syms.append(letter)
        
        node = trie
        for c in syms[::-1]:
            if c not in node:
                return False
            node = node[c]
            if '.' in node:
                return True
        
        return False

# Runtime: 5832 ms, faster than 13.42% of Python3 online submissions for Stream of Characters.
# class StreamChecker:

#     def __init__(self, words: List[str]):
#         self.trie = dict()
#         for word in words:
#             node = self.trie
#             for c in word:
#                 if c not in node:
#                     node[c] = dict()
#                 node = node[c]
#             node['.'] = '.'

#         self.curs = []

#     def query(self, letter: str) -> bool:
#         trie, curs = self.trie, self.curs
        
#         curs = [cur[letter] for cur in curs if letter in cur]
#         if letter in trie:
#             curs.append(trie[letter])
#         self.curs = curs

#         return any('.' in cur for cur in curs)


from collections import defaultdict

def routing():
    return defaultdict(routing)


class StreamChecker:
    def __init__(self, words: List[str]):
        self.router = routing()
        #print(f'{words=}')
        for word in words:
            root = self.router
            for letter in word:
                root = root[letter]
            root[\"*\"] = word
        self.queries = []

    def query(self, letter: str) -> bool:
        #print(f'{letter=} {len(self.queries)=}')
        new_queries, matches = [], []
        self.queries.append(self.router)
        for q in self.queries:
            if letter in q:
                q = q[letter]
                partials = len(q)
                if '*' in q:
                    matches.append(q[\"*\"])
                    partials -= 1
                if partials:
                    new_queries.append(q)
        self.queries = new_queries
        #print(f'{matches=}')
        return bool(matches)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            d = self.trie
            for c in word:
                if c not in d:
                    d[c] = {}
                d = d[c]
            d['*'] = True
        self.open_words = []

    def query(self, letter: str) -> bool:
        found = False
        new_open_words = []
        if letter in self.trie:
            new_open_words.append(self.trie[letter])
            if '*' in self.trie[letter]:
                found = True
        for word in self.open_words:
            if letter in word:
                if '*' in word[letter]:
                    found = True
                new_open_words.append(word[letter])
        self.open_words = new_open_words
        return found


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.check = []
        for w in words:
            d = self.trie
            for c in w:
                _d = d.get(c, {})
                d[c] = _d
                d = _d
            d['.'] = True

    def query(self, letter: str) -> bool:
        next_check = []
        found = False
        for d in self.check + [self.trie]:
            if letter in d:
                _d = d[letter]
                if '.' in _d:
                    found = True
                next_check.append(_d)
        self.check = next_check
        return found

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


TERM_CHAR = '\\0'

def build_trie(words):
    trie = {}
    
    for word in words:
        current = trie
        for c in word:
            if c not in current:
                current[c] = {}
            current = current[c]
            
        current[TERM_CHAR] = True
        
    return trie

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = build_trie(words)
        
        self.trie_currents = []

    def query(self, letter: str) -> bool:
        found = False
        next_tries = []
        for current in self.trie_currents + [self.trie]:
            if letter in current:
                next_tries.append(current[letter])
                if current[letter].get(TERM_CHAR):
                    found = True
                    
        self.trie_currents = next_tries
                    
        return found
                
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self._values = set()
        self.next = None
        
    def insert(self, value):
        self._values.add(value)
    
    def has(self, value):
        return value in self._values


class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = TrieNode()
        self.q = ''
        self.chars = set()
        self.words = set()
        
        for word in words:
            curr = self.root
            for index in range(len(word) - 1, -1, -1):
                char = word[index]
                curr.insert(char)
                self.chars.add(char)
                if not curr.__next__: curr.next = TrieNode()
                curr = curr.__next__
                
            self.words.add(word)
    
    def query(self, letter: str) -> bool:
        if letter not in self.chars:
            self.q = ''
            return False
        
        self.q = letter + self.q
        curr = self.root
        sub_q = ''
        for char in self.q:
            if not curr.has(char):
                return False
            sub_q = char + sub_q
            if sub_q in self.words:
                return True
            
            curr = curr.__next__
            
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


# 08-23-2020
# Day 23 stream of characters

class StreamChecker:

    def __init__(self, words: List[str]):

        trie = dict()
        for word in words:
            t = trie
            for c in word:
                if not c in t:
                    t[c] = dict()
                t = t[c]

            t[None] = True

        self.trie = trie
        self.current_tries = []
        

    def query(self, letter: str) -> bool:
        new_tries = []
        res = False
        for trie in self.current_tries:
            if letter in trie:
                trie = trie[letter]
                new_tries.append(trie)

                res = res | trie.get(None, False)

        if letter in self.trie:
            t = self.trie.copy()
            t = t[letter]
            res = res | t.get(None, False)
            new_tries.append(t)
            

        self.current_tries = new_tries
        
        return res

                
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.ord_a = ord('a')
        stop_ord = ord('z') - self.ord_a + 1
        self.trie = [None] * stop_ord
        self.trie.append(False)
        ord_l = 0
        for word in words:
            current = self.trie
            for l in reversed(word):
                ord_l = ord(l)-self.ord_a
                if current[ord_l] is None:
                    current[ord_l] = [None] * stop_ord
                    current[ord_l].append(False)
                current = current[ord_l]
            current[-1] = True
        #self.paths = []
        #self.start = 0
        self.stream = []

    def query(self, letter: str) -> bool:
        
        result = False
        #print()
        #print(\"letter: {0}\".format(letter))
        #print(self.paths)
        ord_l = ord(letter) - self.ord_a
        self.stream.append(ord_l)
        #while (self.start+1) < len(self.paths) and self.paths[self.start] is None:
        #    self.start+=1
        #for path in range(self.start,len(self.paths)):
        #    if not self.paths[path] is None:
        #        if not self.paths[path][ord_l] is None:
        #            self.paths[path] = self.paths[path][ord_l]
        #            result = result | self.paths[path][-1]
        #        else:
        #            self.paths[path] = None
        #if not self.trie[ord_l] is None:
        #    self.paths.append(self.trie[ord_l])
        #    result = self.trie[ord_l][-1] | result
        #print(self.paths)
        current = self.trie
        for l in self.stream[::-1]:
            current = current[l]
            if current is None:
                return False
            elif current[-1]:
                return True
        return current[-1]


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = trie = {}
        for word in words:
            node = trie
            for c in word:
                node = node.setdefault(c, {})
            node['*'] = word
        self.candidates = []

    def query(self, letter: str) -> bool:
        new = []
        exists = False
        for candidate in self.candidates + [self.trie]:
            if letter in candidate:
                new.append(candidate[letter])
                if candidate[letter].get('*'):
                    exists = True
        self.candidates = new
        return exists
                


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    def __init__(self):
        self.children = defaultdict(lambda: False)
    def insert(self,word):
        if word == '':
            self.children['@'] = True
        else:
            child = self.children[word[0]]
            if child:
                child.insert(word[1:])
            else:
                newChild = Trie()
                newChild.insert(word[1:])
                self.children[word[0]] = newChild
                
class StreamChecker:
    def __init__(self, words: List[str]):
        self.root = Trie()
        for word in words:
            self.root.insert(word)
        self.pointers = []

    def query(self, letter: str) -> bool:
        newPointers = []
        # print(self.pointers)
        retFlag = False
        if letter in self.root.children:
            newPointers.append(self.root.children[letter])
            if '@' in self.root.children[letter].children:
                retFlag = True
        for p in self.pointers:
            newP = p.children[letter]
            if newP:
                newPointers.append(newP)
                if '@' in newP.children:
                    retFlag = True
        self.pointers = newPointers
        return retFlag


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


import queue
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.max_len = 0
        for w in words:
            if w:
                p = self.trie
                self.max_len = max(self.max_len, len(w))
                for idx in range(len(w) - 1, 0, -1):
                    ch = w[idx]
                    if not ch in p:
                        p[ch] = {}
                    p = p[ch]
                p[w[0]] = {'$':None}
        self.letters = []

    def query(self, letter: str) -> bool:
        self.letters.append(letter)
        p = self.trie
        idx = len(self.letters) - 1
        while p and idx >= max(len(self.letters) - self.max_len, 0):
            if '$' in p:
                return True
            l = self.letters[idx]
            if l in p:
                p = p[l]
            else:
                return False
            idx -= 1
        else:
            return '$' in p
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = {}
        self.state = []
        for word in words:
            curr = self.root
            for c in list(word):
                if c not in curr:
                    curr[c] = {}
                curr = curr[c]
            curr['*'] = {}
        

    def query(self, letter: str) -> bool:
        ret = False
        new_state = []
        if letter in self.root:
            self.state.append(self.root)
        for s in self.state:
            if letter in s:
                s = s[letter]
                if '*' in s:
                    ret = True
                new_state.append(s)
        self.state = new_state
        return ret
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.letters = []
        for w in words:
            cur = self.trie
            for l in w[::-1]:
                if not l in cur:
                    cur[l] = {}
                cur = cur[l]
            cur['end'] = {}

    def query(self, letter: str) -> bool:
        self.letters.append(letter)
        cur = self.trie
        for l in self.letters[::-1]:
            if not l in cur:
                return False
            cur = cur[l]
            if 'end' in cur:
                return True
        return False
        
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        Trie = lambda: defaultdict(Trie)
        self.root = Trie()
        self.end = True
        self.words = words
        self.prevs = []
        
        for i, word in enumerate (words):
            reduce (dict.__getitem__, word, self.root)[self.end] = i
        

    def query(self, letter: str) -> bool:
        result = False
        self.prevs.append(self.root)
        if self.prevs:
            new_prevs = []
            for prev in self.prevs:
                if letter in prev:
                    new_prevs.append(prev[letter])
                    result = result or self.end in new_prevs[-1]
            self.prevs = new_prevs
        return result
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)



import functools
class StreamChecker(object):

    def __init__(self, words):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in words: functools.reduce(dict.__getitem__, w, self.trie)['#'] = True
        self.waiting = []

    def query(self, letter):
        self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any(\"#\" in node for node in self.waiting)
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class TrieNode:
    def __init__(self):
        self.children, self.end_node = {}, False
         
class Trie:
    def __init__(self):
        self.root = TrieNode()

    def insert(self, word):
        root = self.root
        for symbol in word:
            root = root.children.setdefault(symbol, TrieNode())
        root.end_node = True        

        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie()
        self.stream = []
        for word in words: self.trie.insert(word[::-1])

    def query(self, letter: str) -> bool:
        self.stream.append(letter)
        cur = self.trie.root
        for c in self.stream[::-1]:
            if c in cur.children:
                cur = cur.children[c]
                if cur.end_node: return True
            else: break
        return False
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
    prefixes = []

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            d = self.trie
            for letter in word:
                if letter not in d:
                    d[letter] = {}
                d = d[letter]
            d['end'] = True

    def query(self, letter: str) -> bool:
        self.prefixes = [node[letter] for node in self.prefixes + [self.trie] if letter in node]
        # if letter in self.trie:
        #     self.prefixes.append(self.trie[letter])
        return any('end' in node for node in self.prefixes)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    def __init__(self):
        self.trie = {}
        
    def add_word(self,word):
        nextLevel = self.trie
        for i,char in enumerate(word):
            isWord = i == len(word) - 1
            if char in nextLevel:
                if isWord:
                    nextLevel[char].isWord = True
                nextLevel = nextLevel[char].children
            else:
                node = TrieNode(char, isWord)
                nextLevel[char] = node
                nextLevel = nextLevel[char].children
            
        
class TrieNode:
    def __init__(self, char, isWord = False):
        self.char = char
        self.isWord = isWord
        self.children = {}


class StreamChecker:

    def __init__(self, words: List[str]):
        self.words = set(words)
        self.trie = Trie()
        for word in words:
            self.trie.add_word(word)
            
        self.nextLevels = []
        self.count = 0

    def query(self, letter: str) -> bool:
        nextLevels = []
        isWord = False
        if len(self.nextLevels):
            for level in self.nextLevels:
                if letter in level:
                    if level[letter].isWord:
                        isWord = True
                    nextLevels.append(level[letter].children)
        
        if letter in self.trie.trie:
            nextLevels.append( self.trie.trie[letter].children )
            if self.trie.trie[letter].isWord:
                isWord = True
                
        self.nextLevels = nextLevels
    
        return isWord
    


class StreamChecker(object):

    def __init__(self, words):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in words: reduce(dict.__getitem__, w, self.trie)['#'] = True
        self.waiting = []

    def query(self, letter):
        self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any(\"#\" in node for node in self.waiting)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.entries = {}
        for word in words:
            curNode = self.entries           
            for i in range(len(word)):
                cur = word[i]
                if cur not in curNode:
                    curNode[cur] = {}
                curNode = curNode[cur]
            curNode[\"#\"] = True
        self.nodes = []

    def query(self, letter: str) -> bool:
        res = False
        self.nodes.append(self.entries)
        new_nodes = []
        for node in self.nodes:
            if letter in node:
                node = node[letter]
                if \"#\" in node:
                    res = True
                new_nodes.append(node)
        self.nodes = new_nodes     
        return res

class StreamChecker:
    class Node:
        def __init__(self, isWord=False):
            self.children = [None]*26
            self.isWord = isWord
            
    import queue
    def __init__(self, words: List[str]):
        self.root = self.Node()
        self.N = 0 # maxWordLength
        for word in words:
            self.N = max(self.N, len(word))
            cursor = self.root
            for c in reversed(word):
                if next := cursor.children[ord(c)-97]:
                    cursor = next
                else:
                    newNode = self.Node()
                    cursor.children[ord(c)-97] = newNode
                    cursor = newNode
            cursor.isWord = True
        
        # self.queue = queue.Queue(maxsize=maxWordLen)
        self.buffer = [None]*self.N
        self.bIdx = self.N

    def query(self, letter: str) -> bool:
        # advance or terminate cursors
        self.bIdx = (self.bIdx - 1) % self.N
        self.buffer[self.bIdx] = letter
        
        cursor = self.root
        for i in range(self.bIdx, self.N):
            if next := cursor.children[ord(self.buffer[i])-97]:
                if next.isWord:
                    return True
                cursor = next
            else:
                return False
        for i in range(self.bIdx):
            if self.buffer[i]:
                if next := cursor.children[ord(self.buffer[i])-97]:
                    if next.isWord:
                        return True
                    cursor = next
                else:
                    return False        
        return False

class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = {}
        for word in words:
            curnode = self.root
            for ch in word:
                if ch not in curnode:
                    curnode[ch] = {}
                curnode = curnode[ch]
            curnode['is_end'] = True
        self.leads = [self.root] # the pointers to the threads we follow right now

    def query(self, letter: str) -> bool:
        next_leads = [self.root]
        found_word = False
        for lead in self.leads:
            if letter in lead:
                new_lead = lead[letter]
                next_leads.append(new_lead)
                if 'is_end' in new_lead:
                    found_word = True
        self.leads = next_leads
        return found_word

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = collections.defaultdict()
        for word in words:
            root = self.trie
            for c in word:
                root = root.setdefault(c, {})
            root[\"#\"] = \"#\"
        self.cache = []
    
    def query(self, letter: str) -> bool:
        next_cache = []
        for node in self.cache + [self.trie]:
            if letter in node:
                next_cache.append(node[letter])
        self.cache = next_cache
        for node in self.cache:
            if '#' in node:
                return True
        return False

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.waitlist = []
        self.trie = {}
        for word in words:
            t = self.trie
            for char in word:
                if char not in t:
                    t[char] = {}
                t = t[char]
            t['#'] = \"#\"
        
    def query(self, letter: str) -> bool:
        waitlist = []
        if letter in self.trie:
            waitlist.append(self.trie[letter])
        
        for item in self.waitlist:
            if letter in item:
                waitlist.append(item[letter])
        self.waitlist = waitlist
        return any([\"#\" in i for i in self.waitlist])
        
        
# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in words: reduce(dict.__getitem__, w, self.trie)['#'] = True
        self.waiting = []

    def query(self, letter):
        self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any(\"#\" in node for node in self.waiting)

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class Trie:
    def __init__(self):
        self.children = defaultdict(bool)
        # self.children = {}
    def insert(self,word):
        if word == '':
            self.children['@'] = True
        else:
            child = self.children[word[0]]
            if child:
                child.insert(word[1:])
            else:
                newChild = Trie()
                newChild.insert(word[1:])
                self.children[word[0]] = newChild
                
class StreamChecker:
    def __init__(self, words: List[str]):
        self.root = Trie()
        for word in words:
            self.root.insert(word)
        self.pointers = []

    def query(self, letter: str) -> bool:
        newPointers = []
        retFlag = False
        self.pointers.append(self.root)
        # if letter in self.root.children:
        #     newPointers.append(self.root.children[letter])
        #     if '@' in self.root.children[letter].children:
        #         retFlag = True
        for p in self.pointers:
            newP = p.children[letter]
            if newP:
                newPointers.append(newP)
                if '@' in newP.children:
                    retFlag = True
        self.pointers = newPointers
        return retFlag

class StreamChecker:

    def __init__(self, words: List[str]):
        # construct a trie (a dict of dicts)
        self.root = {}
        for word in words:
            sub = self.root
            for c in word:
                sub = sub.setdefault(c, {})
            sub['0'] = None
        self.current = []

    def query(self, letter: str) -> bool:
        newQueries = []
        checker = False
        for query in self.current:
            if letter in query:
                nextQuery = query[letter]
                checker = checker or '0' in nextQuery
                newQueries.append(nextQuery)
        if letter in self.root:
            nextQuery = self.root[letter]
            checker = checker or '0' in nextQuery
            newQueries.append(nextQuery)
        self.current = newQueries
        return checker


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = {}
        for word in words:
            node = self.root
            for c in word:
                node.setdefault(c, {})
                node = node[c]
            node[''] = True
        self.ptrs = []

    def query(self, letter: str) -> bool:
        ptrs = self.ptrs
        ptrs.append(self.root)
        i, L = 0, len(ptrs)
        found = False
        while i < L:
            if letter in ptrs[i]:
                ptrs[i] = ptrs[i][letter]
                if '' in ptrs[i]:
                    found = True
                i += 1
            else:
                ptrs[i] = ptrs[L-1]
                ptrs.pop()
                L -= 1
        return found


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    def __init__(self):
        self.children = defaultdict(bool)
        # self.children = {}
    def insert(self,word):
        if word == '':
            self.children['@'] = True
        else:
            child = self.children[word[0]]
            if child:
                child.insert(word[1:])
            else:
                newChild = Trie()
                newChild.insert(word[1:])
                self.children[word[0]] = newChild
                
class StreamChecker:
    def __init__(self, words: List[str]):
        self.root = Trie()
        for word in words:
            self.root.insert(word)
        self.pointers = []

    def query(self, letter: str) -> bool:
        newPointers = []
        retFlag = False
        self.pointers.append(self.root)
        for p in self.pointers:
            newP = p.children[letter]
            if newP:
                newPointers.append(newP)
                if '@' in newP.children:
                    retFlag = True
        self.pointers = newPointers
        return retFlag

class StreamChecker:

    def __init__(self, words: List[str]):
        self.context = []
        self.map = [{}, False]
        
        for w in words:
            it = self.map
            for c in w:
                if c not in it[0]:
                    it[0][c] = [{}, False]
                it = it[0][c]
            it[1] = True

    def query(self, letter: str) -> bool:
        new_context = []
        for m in self.context:
            if letter in m[0]:
                new_context.append(m[0][letter])
        
        if letter in self.map[0]:
            new_context.append(self.map[0][letter])
            
        self.context = new_context
        for m in self.context:
            if m[1]:
                return True
        return False
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.Dict = collections.defaultdict(set)
        self.queries = ''
        for word in words:
            self.Dict[word[-1]].add(word)

    def query(self, letter: str) -> bool:
        if letter not in self.Dict:
            self.queries += letter
            return False
        else:
            temp = set([len(x) for x in self.Dict[letter]])
            self.queries += letter
            for length in temp:
                if (length <= len(self.queries)) and (self.queries[-1:-length-1:-1][::-1] in self.Dict[letter]):
                    return True
                

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie(dict):
    word = False
    def add(self, word):
        t = self
        for c in word:
            if c not in t:
                t[c] = Trie()
            t = t[c]
        t.word = True
        

class StreamChecker:
    def __init__(self, words: List[str]):
        self.t = Trie()
        for w in words:
            self.t.add(w)
        self.s = []

    def query(self, c: str) -> bool:
        self.s = [t[c] for t in self.s if c in t]
        if c in self.t:
            self.s.append(self.t[c])
        return any(t.word for t in self.s)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.waitlist = []
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for word in words:
            temp_dict = self.trie
            for letter in word:
                temp_dict = temp_dict[letter]
            temp_dict['#'] = True

    def query(self, letter: str) -> bool:
        waitlist = []
        if letter in self.trie:
            waitlist.append(self.trie[letter])
        for item in self.waitlist:
            if letter in item:
                waitlist.append(item[letter])
        self.waitlist = waitlist
        return any('#' in item for item in self.waitlist)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
    class TrieNode:
        def __init__(self):
            self.d = {}        
            self.word = False
            
        def add(self, word):    
            node = self
            for c in word:
                if c not in node.d:
                    node.d[c] = StreamChecker.TrieNode()
                node = node.d[c]    
            node.word = True    
            
        def __repr__(self):
            return f'{self.d}'    
            
    def __init__(self, words: List[str]):
        t = self.TrieNode()
        for word in words:
            t.add(word)    
        self.root = t    
        self.tries = []
    
    def query(self, letter: str) -> bool:
        self.tries = [e.d[letter] for e in self.tries if letter in e.d]      
        if letter in self.root.d:
            self.tries.append(self.root.d[letter])        
        print((len(self.tries)))    
        return any([e.word for e in self.tries])    

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = dict()
        for word in words:
            d = self.trie
            for char in word:
                if char not in d:
                    d[char] = dict()
                d = d[char]
            d['*'] = False            
                
        self.recent = list()
        

    def query(self, letter: str) -> bool:
        self.recent = [d[letter] for d in self.recent if letter in d]
        if letter in self.trie:
            self.recent.append(self.trie[letter])
        return any('*' in d for d in self.recent)
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = {}
        for word in words:
            node = self.root
            for c in word:
                node = node.setdefault(c, {})
            node['is_end'] = True
        self.running = []

    def query(self, letter: str) -> bool:
        survived = []
        found = False

        if letter in self.root:
            self.running.append(self.root)

        for node in self.running:
            if letter in node:
                survived.append(node[letter])
                found = found or 'is_end' in survived[-1]

        self.running = survived
        return found

class TrieNode:
        
    def __init__(self):
        self.is_word = False
        self.children = dict()

class StreamChecker:
    \"\"\"Seems super slow?...\"\"\"

    def __init__(self, words: List[str]):
        self._root = TrieNode()
        self._valid_nodes = list()
        for word in words:
            self._insert(word)
        
            
    def _insert(self, word: str):
        node = self._root
        for letter in word:
            if letter not in node.children:
                node.children[letter] = TrieNode()
            node = node.children[letter]
        node.is_word = True

    def query(self, letter: str) -> bool:
        # Shallow copy should be enough
        # node = copy.copy(self._root)
        node = self._root
        self._valid_nodes.append(node)
        next_valid_nodes = list()
        found = False
        for node in self._valid_nodes:
            if letter in node.children:
                node = node.children[letter]
                next_valid_nodes.append(node)
                if node.is_word:
                    found = True
        self._valid_nodes = next_valid_nodes
        return found
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

from collections import deque
class Node:
    def __init__(self):
        self.child = dict()
        self.end = False
class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = Node()
        
        for i in words:
            self.insert(self.root,i[::-1])
        self.key = deque()
        #print(self.root.child)
    def insert(self,root,key):
        for i in key:
            if root.child.get(i,None) == None:
                root.child[i] = Node()
            root = root.child[i]
        root.end = True
    def query(self, letter: str) -> bool:
        self.key.appendleft(letter)
        curr = self.root
        #print(self.key)
        for i in self.key:
            if curr.child.get(i,None) == None:break
            curr = curr.child[i]
            if curr.end:return True
        return False
            
        
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Node:
    def __init__(self, val='.'):
        self.val = val
        self.children = {}
        self.is_word = False    
    
class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = self.__init_trie(words)
        self.q = []

    def query(self, letter: str) -> bool:
        self.q.append(self.root)
        new_q = []
        found = False
        for node in self.q:
            if letter in node.children:
                child_node = node.children[letter]
                new_q.append(child_node)
                if child_node.is_word:
                    found = True
        self.q = new_q
        return found    
    
    def __init_trie(self, words):
        root = Node()
        for word in words:
            cur = root
            for i, ch in enumerate(word):
                if ch not in cur.children:
                    cur.children[ch] = Node(ch)
                cur = cur.children[ch]
            cur.is_word = True
        return root

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:
    class TrieNode:
        def __init__(self):
            self.d = {}        
            self.word = False
            
        def add(self, word):    
            node = self
            for c in word:
                if c not in node.d:
                    node.d[c] = StreamChecker.TrieNode()
                node = node.d[c]    
            node.word = True    
            
        def __repr__(self):
            return f'{self.d}'    
            
    def __init__(self, words: List[str]):
        t = self.TrieNode()
        for word in words:
            t.add(word)    
        self.root = t    
        self.tries = []
    
    def query(self, letter: str) -> bool:
        self.tries = [e.d[letter] for e in self.tries if letter in e.d]      
        if letter in self.root.d:
            self.tries.append(self.root.d[letter])        
        return any([e.word for e in self.tries])    

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    def __init__(self, char):
        self.char = char
        self.children = {}
        self.isEnd = False
        
class TireTree:
    def __init__(self):
        self.root = Trie('')
        
    def insert(self, word):
        cur = self.root
        for c in word:
            if c not in cur.children:
                cur.children[c] = Trie(c)
                cur = cur.children[c]
            else:
                cur = cur.children[c]
        cur.isEnd = True
    
    def search(self, word, cur):
        for c in word:
            if c not in cur.children:
                return False
            
            cur = cur[c]
        return cur.isEnd
    

class StreamChecker:

    def __init__(self, words: List[str]):
        self.tree = TireTree()
        for word in words:
            self.tree.insert(word)
        self.root = self.tree.root
        self.paths = [self.root]
        

    def query(self, letter: str) -> bool:
        nextpaths = [self.root]
        flag = False
        for p in self.paths:
            if letter in p.children:
                node = p.children[letter]
                nextpaths.append(node)
                        
                if node.isEnd:
                    flag = True
                
        self.paths = nextpaths
        return flag
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self._values = set()
        self.next = None
        
    def insert(self, value):
        self._values.add(value)
    
    def has(self, value):
        return value in self._values
    
    def __str__(self):
        return f'Node {self._values} | next -> {self.next}'


class StreamChecker:

    def __init__(self, words: List[str]):
        self.root = TrieNode()
        self.q = ''
        self.chars = set()
        self.words = set()
        
        for word in words:
            curr = self.root
            for index in range(len(word) - 1, -1, -1):
                char = word[index]
                curr.insert(char)
                self.chars.add(char)
                if not curr.__next__: curr.next = TrieNode()
                curr = curr.__next__
                
            self.words.add(word)
        
        print((self.root))
    
    def query(self, letter: str) -> bool:
        if letter not in self.chars:
            self.q = ''
            return False
        
        self.q = letter + self.q
        curr = self.root
        sub_q = ''
        for char in self.q:
            if not curr.has(char):
                return False
            sub_q = char + sub_q
            if sub_q in self.words:
                return True
            
            curr = curr.__next__
            
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Tire:
    def __init__(self, char):
        self.char = char
        self.end = False 
        self.children = {} 
        
    def __repr__(self):
        return '<{}: {}>'.format(self.char, self.end)

class StreamChecker:

    def __init__(self, words: List[str]):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in words: reduce(dict.__getitem__, w, self.trie)['#'] = True
        self.waiting = []

        # self.root = Tire('^')
        # 
        # for word in words:
        #     node = self.root
        #     for char in word:
        #         if char not in node.children:
        #             node.children[char] = Tire(char)
        #         node = node.children[char]
        #     node.end = True    
        #     
        # self.possible_nodes = set() 

    def query(self, letter: str) -> bool:
        self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any(\"#\" in node for node in self.waiting)
 
        # self.possible_nodes.add(self.root)
        # 
        # nxt = set()
        # found = False
        # for node in self.possible_nodes:
        #     if letter in node.children:
        #         nxt.add(node.children[letter])
        #         if node.children[letter].end:
        #             found = True
        # self.possible_nodes = nxt
        # return found
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            t = self.trie
            for w in word:
                if w in t:
                    t = t[w]
                else:
                    t[w] = {}
                    t = t[w]
            t['$'] = word
        self.currWords = [self.trie]
        
    def query(self, letter: str) -> bool:
        q = self.currWords
        q.append(self.trie)
        newQ  = []
        ans = False
        for node in q:
            if letter in node:
                if '$' in node[letter]:
                    ans = True
                newQ.append(node[letter])
        self.currWords = newQ
        return ans
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        T = lambda: collections.defaultdict(T)
        self.trie = T()
        for w in words: reduce(dict.__getitem__, w, self.trie)['#'] = True
        self.waiting = []

        

    def query(self, letter: str) -> bool:
        self.waiting = [node[letter] for node in self.waiting + [self.trie] if letter in node]
        return any(\"#\" in node for node in self.waiting)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:
    def __init__(self, words: List[str]):
        self.d = [{}, False]
        for word in words:
            condition = self.d
            for letter in word:
                if letter not in condition[0]:
                    condition[0][letter] = [{}, False]
                condition = condition[0][letter]
            condition[1] = True
        self.pool = [self.d]
        #print(self.d)

    def query(self, letter: str) -> bool:
        new_pool = [self.d]
        ret = False
        for one in self.pool:
            if letter in one[0]:
                if one[0][letter][1]:
                    ret = True
                new_pool.append(one[0][letter])
        self.pool = new_pool
        #print(self.pool)
                    
        return ret
                    
                
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    class Node:
        def __init__(self):
            self.end=False
            self.child=dict()
            
    def __init__(self, words: List[str]):
        self._root=self.Node()
        self.seq = []
        
        def insert(word=''):
            node = self._root
            for c in reversed(word):
                if c not in node.child:
                    node.child[c]=self.Node()
                node=node.child[c]
            node.end = True
        
        for word in words:
            insert(word)
        

    def _search(self) -> bool:
        node=self._root
        ind=len(self.seq)
        while ind:
            node=node.child.get(self.seq[ind-1], None)
            if not node:
                return False
            if node.end:
                return True
            ind-=1
        return False
        
    def query(self, letter: str) -> bool:
        self.seq.append(letter)
        if len(self.seq)>2000:
            self.seq.pop(0)
        return self._search()


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


import collections
class StreamChecker:

    def __init__(self, words: List[str]):
        
        self.Trie = {}
        
        for word in words:
            parent = self.Trie
            for char in word:
                parent = parent.setdefault(char, {})
            parent['$'] = None
        
        self.waitList = []
        
    def query(self, letter: str) -> bool:
        
        waitList = []
        
        if letter in self.Trie:
            waitList.append(self.Trie[letter])
            
        for currTrie in self.waitList:
            if letter in currTrie:
                waitList.append(currTrie[letter])    
        
        self.waitList = waitList

        return any('$' in item for item in waitList)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Node:
    def __init__(self, v=None):
        self.children: Dict[str, Node] = {}
        self.parent: Node
        self.value = v
    
class Trie:
    def __init__(self):
        self.t = Node() #root;
        self.leaves: Dict[str, List[Node]] = {}
        self.maxLen: int = 0

    def addLeave(self, w:str, n:Node) -> None:
        if w not in list(self.leaves.keys()):
            self.leaves[w] = []
        self.leaves[w].append(n)
        
    def insert(self, w: str) -> None:
        self.maxLen = max(self.maxLen, len(w))
        tl = self.t
        j = 0
        while j<len(w):
            i = w[j]
            n = tl.children.get(i, None)
            if n != None: #this char exist
                tl = n
                j += 1
            else:
                for i in w[j:]:
                    newNode = Node(i)
                    newNode.parent = tl
                    tl.children[i] = newNode
                    tl = newNode
                break
        self.addLeave(tl.value, tl)


class StreamChecker:
    from collections import deque
    
    def __init__(self, words: List[str]):
        self.trie = Trie()
        [self.trie.insert(w) for w in words]
        self.q = deque(maxlen = self.trie.maxLen)
                
    def query(self, letter: str) -> bool:
        self.q.append(letter)
        fl = self.trie.leaves.get(letter, None)
        if fl==None:
            return False
        
        for f in fl:
            i = len(self.q) -2
            if f.parent.value==None: #reached root
                return True #already reach
            while i>=0:
                l = self.q[i]
                if f.parent.value == l:
                    f = f.parent
                    i -= 1
                else:
                    break
                
                if f.parent.value==None: #reached root
                    return True #already reach

        return False
                
            
            


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        
        for word in words:
            node = self.trie
            for c in word:
                node = node.setdefault(c, {})
            node[\"*\"] = None
        self.cur = [self.trie]

    def query(self, letter: str) -> bool:
        ans = False
        new = [self.trie]
        for node in self.cur:
            if letter in node:
                new.append(node[letter])
                if not ans and \"*\" in node[letter]:
                    ans = True
        
        self.cur = new
        return ans
                


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = self.create_trie(words)
        self.l = []

    def create_trie(self, words):
        trie = {}
        for word in words:
            curr = trie
            for ch in word:
                if ch not in curr:
                    curr[ch] = {}
                curr = curr[ch]
            curr['.'] = True
        return trie
            
        
    def query(self, letter: str) -> bool:
        self.l.append(self.trie)
        new_list = []
        is_word = False
        for trie in self.l:
            if letter in trie:
                new_list.append(trie[letter])
                is_word |= '.' in trie[letter]
        self.l = new_list
        return is_word
                
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


def _trie():
    return collections.defaultdict(_trie)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = _trie()
        for word in words:
            trie = self.trie
            for c in word:
                if c not in trie:
                    trie[c] = _trie()
                trie = trie[c]
            trie['END']
        self.activePtr = []
    def query(self, letter: str) -> bool:
        matched = False
        if letter in self.trie:
            self.activePtr.append(self.trie)    
        for i, trie in enumerate(self.activePtr):
            if letter in trie:
                trie = trie[letter]
                if 'END' in trie:
                    matched = True
                    #self.activePtr[i] = None
                self.activePtr[i] = trie
            else :
                self.activePtr[i] = None
        self.activePtr = [t for t in self.activePtr if t is not None]        
        return matched

# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Trie:
    
    def __init__(self):
        self.root = dict()
        self.ptr = []
        
    def add(self, word):
        curr = self.root
        for c in word:
            if not c in curr:
                curr[c] = dict()
            curr = curr[c]
        
        curr['$'] = dict()
        
    def search(self, c):
        self.ptr.append(self.root)
        new_ptr = []
        ans = False
        for ptr in self.ptr:
            if c in ptr:
                new_ptr.append(ptr[c])
        self.ptr = new_ptr
        
        return any(['$' in p for p in self.ptr])
    
class StreamChecker:

    def __init__(self, words: List[str]):
        self.T = Trie()
        for word in words:
            self.T.add(word)

    def query(self, letter: str) -> bool:
        return self.T.search(letter)


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class TrieNode:
    def __init__(self):
        self.children = {}
        self.leaf = False

class StreamChecker:

    def __init__(self, words: List[str]):
        # leads is a collection of trie nodes
        self.trie = TrieNode()
        for word in words:
            node = self.trie
            for i in range(len(word)):
                c = word[i]
                if c not in node.children:
                    node.children[c] = TrieNode()
                node = node.children[c]
                if i == len(word) - 1:
                    node.leaf = True
        self.leads = []

    def query(self, letter: str) -> bool:
        new_leads = []
        result = False
        for lead in self.leads:
            if letter in lead.children:
                node = lead.children[letter]
                if node.leaf:
                    result = True
                new_leads.append(node)
        if letter in self.trie.children:
            if self.trie.children[letter].leaf:
                result = True
            new_leads.append(self.trie.children[letter])
        self.leads = new_leads
        return result
                
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class Node:
    def __init__(self, val='', endWord = False):
        self.val = val
        self.endWord = endWord
        self.children = dict()
        
class Trie:
    def __init__(self, words):
        self.root = Node()
        for word in words:
            self.insertWord(word)
        
    def insertWord(self, word):
        currentNode = self.root
        for letter in word:
            if not letter in currentNode.children:
                currentNode.children[letter] = Node(letter)
            currentNode = currentNode.children[letter]
        currentNode.endWord = True

        
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = Trie(words)
        self.trieRoot = self.trie.root
        self.currentNodes = []
        

    def query(self, letter: str) -> bool:
        newNodes = []
        if letter in self.trieRoot.children:
            newNodes.append(self.trieRoot.children[letter])
            
        for node in self.currentNodes:
            if letter in node.children:
                newNodes.append(node.children[letter])
                
        self.currentNodes = newNodes
        for node in self.currentNodes:
            if node.endWord:
                return True
            
        return False
        
        
            
        


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)


class StreamChecker:

    def __init__(self, words: List[str]):
        self.size = len(max(words, key=len))
        self.words = set(words)
        self.curr = \"\"

    def query(self, letter: str) -> bool:
        #try each word with the corresponding last number of letters
        #
        self.curr = self.curr + letter
        self.curr = self.curr[-self.size:]
        for w in self.words:
            length = len(w)
            if self.curr[-length:] == w:
                return True
        
        return False


# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        for word in words:
            self.trie_insert(word)
        self.searches = []
    
    def trie_insert(self, word):
        curr = self.trie
        for letter in word:
            if letter not in curr:
                curr[letter] = {}
            curr = curr[letter]
        curr['*'] = True # mark last node as a word
    
    
    def query(self, letter: str) -> bool:
        self.searches.append(self.trie)
        self.searches = [node.get(letter) for node in self.searches if letter in node]
        return any('*' in node for node in self.searches)
                
        



# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)