【问题标题】:Matching Two Large Sets of Strings in C#在 C# 中匹配两个大字符串集
【发布时间】:2011-01-07 00:11:02
【问题描述】:

情况如下:

我有一个网页,我已将其作为字符串抓取。

我在 MSSQL 数据库中有几个字段。例如,汽车型号,它有一个 ID 和一个名称,例如 Mustang 或 Civic。它预装了大多数车型。

我想为我的模型表中的任何行找到任何匹配项。因此,如果我的模型表中有 Civic、Mustang 和 E350,我想在我抓取的页面上找到这三个中的任何一个。

在 C# 中执行此操作的有效方法是什么。我正在使用 LINQ to SQL 与数据库交互。

创建所有模型的字典、标记页面并遍历标记是否有意义?还是应该只遍历标记并使用 WHERE 子句并询问数据库是否匹配?

    //Dictionary dic contains all models from the DB, with the name being the key and the id being the value...
    foreach(string pageToken in pageTokens)
    {
         if(dic.ContainsKey(pageToken)) 
         {
              //Do what I need to do
         }
    }

这两种方法对我来说似乎都很糟糕。关于我应该做什么的任何建议?我想有固定交叉点的东西可能会很好?

这些方法都没有解决当模型名称超过一个单词时会发生的情况......比如“F150 Extended Cab”。对此有什么想法?

【问题讨论】:

  • 您是否已经对文本进行了分解以确定哪一段文本是汽车?例如,页面可能以可预测的方式构建以提取匹配项。还是这是一大块尚未评估的文本?
  • 这是一个巨大的文本块。克雷格列表。标题很可能包含模型。但是模型问题是为了说明目的。我还有很多其他的东西需要找到。

标签: c# sql search dictionary


【解决方案1】:

在较大的文本中搜索多个字符串是一个众所周知的问题,并且已经进行了重要的研究以使其更快。两种最流行和最有效的方法是Aho-Corasick Algorithm(我推荐这个)和Rabin-Karp Algorithm。他们使用了一些预处理,但比 naieve 方法复杂且速度快几个数量级(naieve 方法是最坏情况 O(m*n^2*p) 其中 m 是长字符串的长度 [你的网页刮],n 是针的平均长度,p 是针的数量)。 Aho-Corsaik 是线性的。 A C# implementation of it can be found at CodeProject for free.

编辑:糟糕,我对 Aho-Corasick 的复杂性有误——它与输入字符串的数量和长度 + 正在分析的字符串的大小 [被抓取的文本] 加上匹配的数量成线性关系。但它仍然是线性的,而且线性比三次要好得多:-)。

【讨论】:

  • 我决定在稍后阶段进行处理,这样可以消除性能问题。这是非常有用的信息。
【解决方案2】:

我的第一种方法非常简单:

foreach(string carModel in listOfCarModelsFromDatabase) {
    if(pageText.Contains(carModel) {
        // do something
    }
}

如果上面的速度不够快,我只会开始担心让它更快。汽车型号列表不可能那么大(

【讨论】:

  • 这对于大型模型列表会变得相当低效,但适用于小型列表。
  • 是的,但车型并不多。世界历史上有多少家汽车公司?五十?每个人拥有的最大车型数量是多少?二百?那么世界历史上可能有 50 * 200 = 10000 个模型?这当然是正确的数量级。
  • 我有大约 1500 个对象需要与文本进行比较。
  • 没错,我只是在想象,如果他要“索引”100000 个页面,每个页面有 10 KB 的文本,那大约是 1 gig 的数据,foreach 循环甚至可以说是 500 个模型。跨度>
  • 从字典中匹配字符串是计算机科学中一个很好理解的问题;这个答案就像建议冒泡排序。
【解决方案3】:

您应该使用正则表达式,而不是基于空间的标记。

使用正则表达式,您可以使用空格并且很好,我相信它会比标记和循环遍历可能的值列表更快。

虽然我不确定,但您是如何构建该正则表达式的。

最简单的是,您可以简单地为每个模型构建一个正则表达式,例如

(Model 1|Model 2|Model 3) 

但我确信在正则表达式中有更有效的方法来做到这一点。

【讨论】:

  • 如果有很多模型,正则表达式模式会很大......我不确定它的效率如何。
  • 是的,这肯定是个有趣的问题。
  • 一些正则表达式引擎可能会对其进行优化,但是具有这么多分支的传统 NFA/DFA 会很慢并且内存效率极低。我希望正则表达式的执行比天真的搜索更糟糕
  • 是的,这是 Aho-Corasick、naieve search (IndexOf) 和正则表达式的比较:codeproject.com/KB/recipes/ahocorasick.aspx。正则表达式的性能非常糟糕。
【解决方案4】:

对于进行子字符串匹配的非常简单的解决方案(应该执行得相当好),您可以使用这样的参数化 SQL 查询:

select ModelID, ModelName
from Model
where ? like '%' + ModelName + '%'

? 是一个被整个网页文本替换的参数。

【讨论】:

  • -1:这是天真的、显而易见的解决方案。这在道德上等同于作者发布的“糟糕”解决方案。虽然这对他的目的来说可能足够快,但他有点要求另一种选择。
  • 正在使用什么数据库引擎?一些数据库引擎会自动实现一个好的搜索方法,这会比手动实现 Aho-Corasick 或 Rabin-Karp 更好(更易于维护、更优化、更少数据传输等)。
  • 正如我在回答中所说,这是一个非常简单的解决方案。我认为某些人可能会感兴趣的是 LIKE 的倒置使用 - 许多人不知道可以这样做。
猜你喜欢
  • 2014-11-15
  • 2014-02-11
  • 2019-12-01
  • 1970-01-01
  • 2017-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-05
相关资源
最近更新 更多