我认为在一般情况下,您将无法避免非常糟糕的运行时 - 每个文档中有 5050 对和 10M 文档,所有组合似乎都是可能的。
但是,在典型的现实世界数据中,您很少需要处理“对抗性”输入。一种可能的解决方案是首先计算所有 100K 术语的出现次数,对它们进行排序,然后对于每个术语 X,执行以下操作:
- 如果有许多带有 X 的文档(即不少于文档数量的 1%,或其他一些可调整的部分),以 X 和 Y 的形式对您的索引运行查询,从最流行的术语开始向下,保持一个大小为 10 的堆,用于跟踪最受欢迎的对。你知道 max(docs with X & Y) = max(docs with X, docs with Y),所以很可能你可以尽早缩短这个过程
- 如果带有 X 的文档很少,那么简单地扫描具有该术语的所有文档并自己汇总总数会更加谨慎。
对于表现良好的文档集,其中 100K 项遵循关于文档计数的对数曲线,您将做的工作远远少于 (100)^2 * 10M 的工作,而天真的解决方案在所有情况下都需要这样做。当然,对于表现不佳的文档集,您最终会做更多的工作,但这不应该在现实世界中发生。
至于“不是 100% 准确”,这是一个过于模糊的规范,无法使用。什么样的错误是允许的?有多少?
--- 评论回复(评论太大) ---
a) 考虑确定最多 1 亿个元素。您只需要保存扫描时最好的 1 个 - 同样的原则适用于确定 N 个项目中的前 X 个。将传入的元素添加到二叉堆中,当堆的大小超过 X 时删除最弱的元素。添加结束,您将拥有顶部 X
b) 假设您正在确定前 10 个 X&Y 对,其中 X="Elephant"。假设,在扫描了 1000 个 Y 术语之后,您有一个大小为 10 的堆,其中最小得分对的计数为 300。现在假设您检查的第 1001 个术语的文档计数为 299 - 因为最多只有 299 个文档具有 Y 术语299 个文档也有 X&Y,因此它不可能比您迄今为止拥有的前 10 对中的任何一个更好,并且由于所有 Y 术语都按文档频率排序,实际上您现在知道您没有检查更多对!这是 max 语句向您保证的。
c) 您对每个 X 所做的选择纯粹是一个优化决策。如果您有许多只存在于少量文档中的 X,这是一个很好的问题 - 这意味着每个学期的工作量更少。
d) 如果您可以忍受前 10 个错误的非零概率(对于每个术语),您可能可以通过使用抽样方法而不是对索引进行全面、严格的扫描来减少运行时间。文档索引中的术语 X 越普遍,根据您收集的信息,在您可能拥有正确的前 10 个 X&Y 对之前,您必须扫描的文档(按比例)越少。要得出这方面的确切数字,需要了解基础索引中术语的预期分布。特别是:术语有多少相关性?数字 N(X)/MAXY(X) 一般看起来像什么,其中 N(X) 是带有术语 X 的文档数,MAXY(X) 是具有 X&Y 对的文档数,最大化所有条款 Y != X