Prefix and Suffix Search

hard trie string design

Problem

Implement WordFilter so that f(prefix, suffix) returns the largest index i such that words[i] starts with prefix and ends with suffix, or -1 if none exists.

Inputwords=["apple"]; f("a","e")
Output0
"apple" matches prefix "a" and suffix "e" so index 0 is returned.

class WordFilter:
    def __init__(self, words):
        self.trie = {}
        for i, w in enumerate(words):
            for s in range(len(w) + 1):
                key = w[s:] + '#' + w
                node = self.trie
                for ch in key:
                    node = node.setdefault(ch, {})
                    node['$'] = i
    def f(self, prefix, suffix):
        key = suffix + '#' + prefix
        node = self.trie
        for ch in key:
            if ch not in node: return -1
            node = node[ch]
        return node.get('$', -1)
class WordFilter {
  constructor(words) {
    this.trie = {};
    for (let i = 0; i < words.length; i++) {
      const w = words[i];
      for (let s = 0; s <= w.length; s++) {
        const key = w.slice(s) + '#' + w;
        let node = this.trie;
        for (const ch of key) {
          if (!node[ch]) node[ch] = {};
          node = node[ch];
          node.$ = i;
        }
      }
    }
  }
  f(prefix, suffix) {
    const key = suffix + '#' + prefix;
    let node = this.trie;
    for (const ch of key) {
      if (!node[ch]) return -1;
      node = node[ch];
    }
    return node.$ ?? -1;
  }
}
class WordFilter {
  static class Node { Map<Character, Node> next = new HashMap<>(); int idx = -1; }
  Node root = new Node();
  public WordFilter(String[] words) {
    for (int i = 0; i < words.length; i++) {
      String w = words[i];
      for (int s = 0; s <= w.length(); s++) {
        String key = w.substring(s) + "#" + w;
        Node node = root;
        for (char ch : key.toCharArray()) {
          node = node.next.computeIfAbsent(ch, k -> new Node());
          node.idx = i;
        }
      }
    }
  }
  public int f(String prefix, String suffix) {
    String key = suffix + "#" + prefix;
    Node node = root;
    for (char ch : key.toCharArray()) {
      node = node.next.get(ch);
      if (node == null) return -1;
    }
    return node.idx;
  }
}
class WordFilter {
  struct Node { unordered_map<char, Node*> next; int idx = -1; };
  Node* root = new Node();
public:
  WordFilter(vector<string>& words) {
    for (int i = 0; i < (int)words.size(); i++) {
      const string& w = words[i];
      for (int s = 0; s <= (int)w.size(); s++) {
        string key = w.substr(s) + "#" + w;
        Node* node = root;
        for (char ch : key) {
          if (!node->next.count(ch)) node->next[ch] = new Node();
          node = node->next[ch];
          node->idx = i;
        }
      }
    }
  }
  int f(string prefix, string suffix) {
    string key = suffix + "#" + prefix;
    Node* node = root;
    for (char ch : key) {
      if (!node->next.count(ch)) return -1;
      node = node->next[ch];
    }
    return node->idx;
  }
};
Time: O(N L^2) build, O(P + S) query Space: O(N L^2)