LeetCode Solutions

792. Number of Matching Subsequences

Time: $O(|\texttt{S}| + \Sigma |\texttt{words[i]}|)$

Space: $O(\Sigma |\texttt{words[i]}|)$

			

struct TrieNode {
  vector<shared_ptr<TrieNode>> children;
  int count = 0;
  TrieNode() : children(26) {}
};

class Solution {
 public:
  int numMatchingSubseq(string S, vector<string>& words) {
    for (const string& word : words)
      insert(word);

    return dfs(S, 0, root);
  }

 private:
  shared_ptr<TrieNode> root = make_shared<TrieNode>();

  void insert(const string& word) {
    shared_ptr<TrieNode> node = root;
    for (const char c : word) {
      const int i = c - 'a';
      if (node->children[i] == nullptr)
        node->children[i] = make_shared<TrieNode>();
      node = node->children[i];
    }
    ++node->count;
  }

  int dfs(const string& s, int i, shared_ptr<TrieNode> node) {
    int ans = node->count;
    if (i >= s.length())
      return ans;

    for (int j = 0; j < 26; ++j)
      if (node->children[j]) {
        const int index = s.find('a' + j, i);
        if (index != -1)
          ans += dfs(s, index + 1, node->children[j]);
      }

    return ans;
  }
};
			

class TrieNode {
  public TrieNode[] children = new TrieNode[26];
  public int count = 0;
}

class Solution {
  public int numMatchingSubseq(String S, String[] words) {
    for (final String word : words)
      insert(word);

    return dfs(S, 0, root);
  }

  private TrieNode root = new TrieNode();

  private void insert(final String word) {
    TrieNode node = root;
    for (final char c : word.toCharArray()) {
      final int i = c - 'a';
      if (node.children[i] == null)
        node.children[i] = new TrieNode();
      node = node.children[i];
    }
    ++node.count;
  }

  private int dfs(final String s, int i, TrieNode node) {
    int ans = node.count;
    if (i >= s.length())
      return ans;

    for (int j = 0; j < 26; ++j)
      if (node.children[j] != null) {
        final int index = s.indexOf('a' + j, i);
        if (index != -1)
          ans += dfs(s, index + 1, node.children[j]);
      }

    return ans;
  }
}
			

class Solution:
  def numMatchingSubseq(self, s: str, words: List[str]) -> int:
    root = {}

    def insert(word: str) -> None:
      node = root
      for c in word:
        if c not in node:
          node[c] = {'count': 0}
        node = node[c]
      node['count'] += 1

    for word in words:
      insert(word)

    def dfs(s: str, i: int, node: dict) -> int:
      ans = node['count'] if 'count' in node else 0

      if i >= len(s):
        return ans

      for c in string.ascii_lowercase:
        if c in node:
          try:
            index = s.index(c, i)
            ans += dfs(s, index + 1, node[c])
          except ValueError:
            continue

      return ans

    return dfs(s, 0, root)