【发布时间】:2021-12-12 08:04:06
【问题描述】:
我有一个大的短字符串(单词)列表,我想检查它们中的任何一个是否出现在另一个字符串(句子)中。请注意,我不关心实际的单词/空格/标点符号/等。
这是python中典型的解决方案:
def contains_one_of(sentence, words):
for word in words:
if word in sentence:
return word
return None
我见过一些 python one-liners 做同样的事情,但从算法上我能找到的一切似乎基本上都是为所有元素调用 contains 函数。我假设 contains 函数使用一种滑动窗口方法。
我估计复杂度大约是 O(nmo)
其中 n = 列表长度,m = 句子长度,o = 列表中单词的平均长度
对我来说,我认为这可以通过一棵树来改进,但我找不到对这种算法的任何参考。 我基本上设想单词数组变成一棵树,其中一个节点是一个字母,它的所有子节点都是该单词的下一个字母。只要单词简短并且有合理的重叠,我认为这会更有效。
我已经在 python 中实现了这个版本,但我更愿意使用一个利用 C 来比较所有这些字符的包。 如果您知道此算法的名称或执行此操作的软件包的名称,我很想知道。
这是我的版本,我相信很多都可以优化,但我想知道我是否在这里做一些事情。
sentence = "hello there cat, welcome home"
words = ["cat", "car", "cam", "arm", "ace", "arc"]
# build a dict tree per letter
def build_tree(patterns):
root = dict()
for p in patterns:
r = root
for i, c in enumerate(p):
if c not in r:
if i >= len(p) - 1: # last element
r[c] = p
else: # any other element
r[c] = dict()
r = r[c]
return root
# Check if the substring starts with a path through the tree
def starts_with_tree(sub, tree):
level = tree
for c in sub:
if c not in level: # nowhere left to go
return None
elif isinstance(level[c], str): # if we found a string we are at the end
return level[c]
else:
level = level[c] # go deeper
# Check if s contains any path through the tree
def contains_which(s, root):
for i in range(len(s)):
sub = s[i:] # A substring missing the first i characters
result = starts_with_tree(sub, root)
if result:
return result
return None
# build the tree
tree_root = build_tree(words)
print(tree_root)
# search within tree
found = contains_which(sentence, tree_root)
print("Found:", found)
【问题讨论】:
-
您似乎正在寻找全文搜索功能。在这种情况下,您需要一个倒排索引数据结构。
标签: python algorithm tree contains