Stream of Characters

Streaming multi-pattern match — build an Aho-Corasick-like trie over reversed words, walk it with a buffer of recent chars.

Hard
Time O(L) per query (worst) Space O(sum |w|)
LeetCode
5 min read
design trie streaming

Problem#

StreamChecker is initialized with a list of words. query(letter) returns true iff some word ends at the current stream position (i.e., is a suffix of all chars seen so far).

Examples#

  • words=["cd","f","kl"]; query('a')false; query('b')false; query('c')false; query('d')true (“cd”).

Constraints#

  • 1 <= words.length <= 2000, total chars <= 2 * 10^4, up to 4 * 10^4 queries.

Approach#

Insert each word reversed into a trie. Maintain a growing buffer of all chars seen. On each query, walk backward through recent chars (up to the longest word) along the trie; if we ever reach an end-of-word marker, return true.

Solution#

StreamChecker
class StreamChecker {
struct Node { Node* ch[26] = {}; bool end = false; };
Node* root = new Node();
string buf;
int maxLen = 0;
public:
StreamChecker(vector<string>& words) {
for (auto& w : words) {
maxLen = max(maxLen, (int)w.size());
Node* cur = root;
for (int i = (int)w.size() - 1; i >= 0; --i) {
int c = w[i] - 'a';
if (!cur->ch[c]) cur->ch[c] = new Node();
cur = cur->ch[c];
}
cur->end = true;
}
}
bool query(char letter) {
buf.push_back(letter);
Node* cur = root;
int end = (int)buf.size() - 1, lo = max(0, end - maxLen + 1);
for (int i = end; i >= lo; --i) {
int c = buf[i] - 'a';
if (!cur->ch[c]) return false;
cur = cur->ch[c];
if (cur->end) return true;
}
return false;
}
};

Editorial#

Reversing the words lets us start matching from the newest character — exactly the data we have. Walking back at most maxLen chars bounds each query’s work, and the trie sharing keeps memory tight.

Complexity#

  • Time: O(maxLen) per query.
  • Space: O(sum of word lengths).

Concept revision#

Search ESC

Keyboard shortcuts

Shortcuts are disabled while typing in inputs.