Given a list of words and a sentence find all words that appear in the sentence either in whole or as a substring
The theoretically sound version of what you're trying to do is called Aho--Corasick. Implementing the suffix links is somewhat complicated IIRC, so here's an algorithm that just uses the trie.
We consume the text letter by letter. At all times, we maintain a set of nodes in the trie where the traversal can be. Initially this set consists of just the root node. For each letter, we loop through the nodes in the set, descending via the new letter if possible. If the resulting node is a match, great, report it. Regardless, put it in the next set. The next set also contains the root node, since we can start a new match at any time.
Here's my attempt at a quick implementation in Python (untested, no warranty, etc.).
class Trie:
def __init__(self):
self.is_needle = False
self._children = {}
def find(self, text):
node = self
for c in text:
node = node._children.get(c)
if node is None:
break
return node
def insert(self, needle):
node = self
for c in needle:
node = node._children.setdefault(c, Trie())
node.is_needle = True
def count_matches(needles, text):
root = Trie()
for needle in needles:
root.insert(needle)
nodes = [root]
count = 0
for c in text:
next_nodes = [root]
for node in nodes:
next_node = node.find(c)
if next_node is not None:
count += next_node.is_needle
next_nodes.append(next_node)
nodes = next_nodes
return count
print(
count_matches(['red', 'hello', 'how are you', 'hey', 'deployed'],
'hello, This is shared right? how are you doing tonight'))