-2

Given an array of string words, please design a string subsequence matcher.

Implement the SubsequenceMatcher class:

  • SubsequenceMatcher(string words[]): Initializes the object with a pattern array words, and an empty string s.
  • bool addChar(char c): Add a character c to the end of the string s. Return true if at least one string in words is a subsequence of s, false otherwise.

Example:

words = ["abc", "bd", "ace"]
addChar('a') -> false // a
addChar('d') -> false // ad
addChar('b') -> false // adb
addChar('e') -> false // adbe
addChar('c') -> true // adbec, include a subsequence abc

The aim is to minimize the cost of each call to addChar. I find a similar problem leetcode 795, the solution is O(n) for an addChar call, where n is the length of words. Is there a more efficient algorithm?

ZelKnow
  • 1
  • 2

1 Answers1

0

I'm pretty sure the short answer is no, you can't be better than O(n).

Although the simple solution below can be improved:

  1. Have a pointer for each word that points to the first character.
  2. When addChar is called compare with each pointer (i.e. the character it is pointing to) and if it matches move the pointer one step further. If the end of a word is/was reached return true otherwise false.

Improvements:

  • Have a variable that tells you if a word was completed and return always true afterwards without doing anything.
  • Have a map with next char as key and a list or set with the words and pointers as value. Like this you only have to update the words for the given character and then put them at their new location.
  • Preprocess the words and eliminate all the words containing a subsequence of another word.

Here is an alternative algorithm that could be better or worse:

  1. Construct a trie.
  2. Have a map with the next character as key and a list of trie nodes as value.
  3. For every edge of the root: put the root in the map (the edge i.e. the character it is pointing to is the key and the root is added to the corresponding list).
  4. When addChar is called go through the corresponding list and for each node remove it from the list, replace it with the child corresponding to the character and put it in all the lists its pointing to (same as we've done with the root).
  5. If the end of a word is reached return true (always from then on) otherwise false.
maraca
  • 8,468
  • 3
  • 23
  • 45