【问题标题】:Effieciet way to check maching strings present in another string检查另一个字符串中存在的匹配字符串的有效方法
【发布时间】:2019-06-04 05:38:49
【问题描述】:

我有一个关键字列表和另一个较长的字符串(2 或 3 页)。我想找出关键字列表中存在的关键字。 例如

Keywords = [k1, k2, k3 k4, k5, k6 k7 k8]
paragraphs = "This will be 2 to4 page article"

一种简单的方法是

present_keywords = [x for x in keywords if x in paragraphs]

上述算法的时间复杂度为O(m*n) =~ O(n^2)

另一种方式 我可以创建一堆关键字列表,时间复杂度:O(n log n) 然后在堆中搜索段落中的每个单词,时间复杂度为O(n)

注意:关键字是二元组,三元组也是如此,所以第二种方法不起作用。

什么是实现这一目标的有效方法?

一些关键字是 n-gram

许多人在没有考虑这种约束的情况下给出了解决方案。例如 纽约 是一个关键字。拆分段落会将 New 和 York 拆分为不同的单词。在上面的注释中也提到了这一点。

【问题讨论】:

  • 第一种方法会在“健美操”中找到“then”。对吗?
  • Heap 如何将时间复杂度降低到 O(n log m)

标签: python algorithm search data-structures full-text-search


【解决方案1】:

为了降低时间复杂度,我们可以增加空间复杂度。通过keywords 并将它们散列到一个 set() 中,假设每个关键字都是唯一的(如果不是,重复的将被删除)。

然后您可以通过paragraph 并创建一个、两个或三个单词短语,检查它们的存在并在任何这些短语出现在hashedKeywords 时增加它们的计数。时间复杂度为 O(m+n) =~ O(n),但空间复杂度从 O(1) 到 O(n)。

import string # for removing punctuation

# Sample input with bigrams and trigrams in keywords
paragraphs = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
keywords = ['magna', 'lorem ipsum', 'sed do eiusmod', 'aliqua']

# Hash keywords into set for faster look up
hashedKeywords = set()
for keyword in keywords:
    hashedKeywords.add(keyword)

# Strip punctuation from paragraph phrases using translate() and make it case insensitive using lower()
table = str.maketrans({key: None for key in string.punctuation})
wordsInParagraphs = [w.translate(table).lower() for w in paragraphs.split()]

# Initialize for loop
maxGram = 3
wordFrequency = {}

# Loop through words in paragraphs but also create a small list of one, two, or three word phrases. 

for i in range(len(wordsInParagraphs)):
    # List slicing ensures the last word and second to last word will produce a one and two string list, respectively (since slicing past the length of the list will simply return a list up to the last element in Python)
    phrases = wordsInParagraphs[i:i+maxGram] # e.g. ['lorem', 'ipsum', 'dolor']

    # Loop through the one, two, and three word phrases and check if phrase is in keywords
    for j in range(len(phrases)):
        phrase = ' '.join(phrases[0:j+1]) # Join list of strings into a complete string e.g. 'lorem', 'lorem ipsum', and 'lorem ipsum dolor'
        if phrase in hashedKeywords:
            wordFrequency.setdefault(phrase , 0)
            wordFrequency[phrase] += 1
print(wordFrequency)

输出:

{'lorem ipsum': 1, 'sed do eiusmod': 1, 'magna': 1, 'aliqua': 1}

注意:这是在 Python 3 中。如果在 Python 2 中并希望删除标点符号,请参阅this answer

【讨论】:

  • 我认为这是预处理(预先知道的)关键字列表的常用方法的有趣反转。
  • @endyd 您错过了问题的评论。关键字也可能是 n-gram。例如“纽约”。拆分段落会将关键字拆分为“New”和“York”。所以上述功能并不能解决问题。甚至“New”和“York”的计数也会匹配,它们可能或可能已经连续出现。
  • 嗨,对不起,我错过了,因为我不太明白什么是二元组,但是通过你的例子,我明白了。只是一个两个词的关键字。我已经编辑了答案以包括二元组和三元组。
  • @greybeard 真的哈哈。在我编辑的允许二元组和三元组的答案中,我已经完成了更好的散列关键字的方法(因为关键字列表很可能小于文章,并且关键字散列可用于多篇文章)。感谢您的意见。
猜你喜欢
  • 2012-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-08
  • 1970-01-01
  • 2021-08-17
  • 2011-03-24
相关资源
最近更新 更多