使用Python 3,我有一个包含超过100,000个字符串(list1)的列表,每个字符最多300个字符。我还有一个超过900万个子串的列表(list2) - 我想计算list2中子串的元素数量。例如,
list1 = ['cat', 'caa', 'doa', 'oat']
list2 = ['at', 'ca', 'do']
我希望函数返回(映射到list2):
[2, 2, 1]
通常情况下,这很简单,只需要很少。但是,由于列表的大小,我有效率问题。我想找到返回该计数器列表的最快方法。
我已经尝试了列表推导,生成器,地图,各种循环,我还没有找到一种快速的方法来完成这项简单的任务。什么是理论上最快的方法来完成这个目标,最好快速采取O(len(list2))
步骤?
答案 0 :(得分:2)
设置M = len(list1)
和N = len(list2)
对于list2
中的每个N个条目,您将不得不对list1
中的条目进行M比较。这是O(M x N)
最糟糕的运行时间。如果您进一步了解,我们可以将list2
中的每个条目的长度设置为1,list1
中的每个条目的长度为300,然后您的运行时间为O(300M x N)
。< / p>
如果性能确实存在问题,请尝试动态编程。这是一个开始:
1)按照长度的升序排序list2
,如下所示:
['scorch', 'scorching', 'dump', 'dumpster', 'dumpsters']
2)将它们分类到子列表中,使得每个前面的条目都是前进条目的子集,如下所示:
[['scorch', 'scorching'] , ['dump', 'dumpster', 'dumpsters']]
3)现在,如果您与list1
进行比较并且'scorch'
不在那里,那么您也不必搜索'scorching'
。同样,如果'dump'
不在,'dumpster'
或'dumpsters'
注意最差情况下的运行时间仍然相同
答案 1 :(得分:1)
我相信这个任务可以使用Aho Corasick string matching机器在线性时间内解决。 请参阅this回答以获取更多信息(也许您可以从该问题的其他答案中获得想法 - 这几乎是相同的任务,我认为Aho Corasick是理论上最快的解决方法这一点)。
您必须以这种方式修改字符串匹配机器,而不是返回匹配,它会将每个匹配的子字符串的计数器增加一。 (这应该只是一个小修改)。
答案 2 :(得分:0)
不确定如何避免使用某种O(n ** 2)算法。这是一个简单的实现。
>>> def some_sort_of_count(list1, list2):
>>> return [sum(x in y for y in list1) for x in list2]
>>>
>>> list1 = ['cat', 'caa', 'doa', 'oat']
>>> list2 = ['at', 'ca', 'do']
>>> some_sort_of_count(list1, list2)
[2, 2, 1]