我有一个很长的字符串,让我们说astr =“我是一个非常长的字符串,我可以包含很多文本,所以在这里考虑效率”.我还有一个列表alist = [“我”,“我是”,“列表”,“字符串”,“和每个字符串”,“可以由许多单词组成”,“所以想到这里的效率”] .现在,我的字符串列表也有一个相应的整数列表alist_ofints = [1,2,3,4,5,6,7],它表示此列表中每个字符串等于多少个点.
我应该创建一个函数来查找astr中有多少单词出现在列表中,并使用相应的点列表alist_ofints创建一个“点”计数器.因此,在这个例子中,单词“I”,“am a”,“所以想到这里的效率”分别出现两次,一次和一次.这将给我们1 * 2 2 * 1 7 * 1 = 11分.
我想出了两个天真的解决方案.第一个是创建一个查看此字符串列表的函数,并检查每个项目是否在astr中,如果是,则应用明显的后续逻辑.这是低效的,因为我将调查astr a len(alist)次数.那是浪费,不是吗?它很干净,但很低效.
第二个解决方案是将astr列为单词列表,我会检查索引i到索引j的每个单词,其中i是我在列表中的位置,j是我要查找的alist中短语的长度.所以,“am a”是长度为2的短语(因为它有两个单词),所以我会看i =某个数字,j =某个数字1.如果我正在寻找短语“和每个字符串“,i =某个数字,j =某个数字3.所以我在测试这个短语时会看三个字.现在,我认为这也具有相同的时间复杂性.虽然我没有循环遍历astr列表,但是我循环遍历我的单词列表alist len(list(astr))次.此外,我必须创建一个astr列表,这增加了一些复杂性,我想.
所以,到目前为止,我更喜欢第一种解决方案,因为它是最简单,最简单,最干净的解决方案.有一个更好的方法吗?如果你能找到列表理解方式,那就加分吧…
谢谢
注意:我知道list(astr)不会返回单词列表.想象一下,对于这个例子,确实如此.
TLDR:我有两个清单.我需要检查列表中的每个元素是否等于另一个列表中的元素,并创建它们出现的次数.有没有更有效的方法来检查列表1中的每个元素与列表2中的每个其他元素(我认为这是O(n ^ 2))?
最佳答案 更有效的算法可以使用字符串索引(例如,
Suffix Array)索引长字符串astr.然后在索引中的alist中搜索每个条目,并在找到结果时相应地增加点.
索引astr的运行时间是O(n),其中n是astr的长度.
从索引中长度为m的alist中搜索条目是在O(log n)中
总的来说,你应该逃避O(p log n),其中p是alist中的条目数.
例
让我们考虑长字符串astr
I am a very long string
然后相应的后缀数组(全部小写)将是
SA = [1 4 6 11 16 5 2 8 22 15 0 20 12 3 21 14 13 19 9 17 18 7 10]
这些都是astr的后缀(由它们的起始索引表示)排序的词典.例如,SA [9] = 15表示从位置15开始的astr中的字符串(“g string”).
现在让我们假设您的短语列表
alist = [“I am”, “very long”,…]
然后,对于要在后缀数组中搜索事件的每个条目.这是使用后缀数组上的二进制搜索完成的.对于“我是”,这将看起来如下:
首先,您查看后缀数组的中间条目(SA [11] = 20).然后你看一下该索引所代表的后缀(“ing”).由于此后缀大于搜索短语“我是”,因此您需要查看后缀数组的左半部分.继续此二进制搜索,直到找到该短语,或者您确定它不在那里.