我在数据库中有数千个关键字(每个关键字中包含一个或多个单词)的有限列表。我想有效地找到哪些关键字在给定的输入文本中,而不必逐个测试每个关键字(全表扫描)。允许匹配文本中的一些拼写错误的单词会更好但不是必需的。任何算法/文章建议来解决这个问题?
答案 0 :(得分:4)
我认为到目前为止,一些答案误解了所提出的问题。我的理解是你有一个(大的)单词列表和一个(大的)文本正文。你想知道两个列表中哪些词有共同之处,这是正确的吗?
如果是这样,这根本不是一个全文问题。基本上,您只有两个单词列表(原始关键字和输入文本中的单词列表)。如果对两个列表进行排序,则可以同时扫描两个列表并提取共同的单词。
假设关键字列表已经排序,您可以在O(n logn)时间内从文本正文中提取和排序单词,然后同时扫描两个列表是O(n + m)(其中n是文本正文中的单词数和m是关键字列表中的单词数。)
答案 1 :(得分:1)
我不知道您使用的是哪个数据库但知道如果是Oracle,您应该可以访问Oracle Text功能(或者您可以请求您的DBA启用它)。借助CONTAINS
等其他功能以及Oracle Text索引的正确使用,您可以实现您想要的功能,甚至可以查找“拼写错误”的单词。这是通过将CONTAINS
与计算两个字符串之间的Levenshtein distance的函数相结合来完成的。在Oracle Text中,此函数为FUZZY
。
在这个Oracle documentation中有一个完美的例子。
我不太了解其他类型的数据库,但我很确定主要供应商确实有适当的搜索文本。只需快速搜索,即可进行全文搜索:
无论如何,使用内置的DBMS函数/过程要快得多,而不是创建自己的自定义函数,甚至用你的编程语言进行搜索(虽然成千上万的关键字并不是那么多)
编辑:再次阅读你的问题后,Dean Harding的回答我觉得我没有正确回答这个问题。使用Oracle Text,而不是使用CONTAINS
函数,您可以使用MATCHES
函数(请参阅Paragraph 4.1.3),它完全相同:查询存储在表中的关键字列表并返回找到的关键字的ID。我将在下面复制文档中的示例(添加了我自己的评论):
create table queries (
query_id number,
query_string varchar2(80)
);
// Here we populate the table with the keywords
insert into queries values (1, 'oracle');
insert into queries values (2, 'larry or ellison');
insert into queries values (3, 'oracle and text');
insert into queries values (4, 'market share');
create index queryx on queries(query_string)
indextype is ctxsys.ctxrule;
// This query will return the ids of the matched keywords
select query_id from queries
where matches(query_string,
'Oracle announced that its market share in databases
increased over the last year.')>0
我希望它比我的第一次尝试更有帮助。
Edit2:只是为了添加你不使用这种方法执行全表扫描,因为你正在使用域索引。
答案 2 :(得分:1)
您可以使用Apache Lucene或Apache Solr(基于Lucene的HTTP全文服务)等解决方案来实现此目标。
Apache Lucene提供了一个API来索引您想象的任何数据。
根据您的需求,您可以选择其中一种:
关于拼写检查功能,Solr包含使用built-in component
的拼写检查“建议”一些教程/信息:
答案 3 :(得分:1)
您可以使用所描述的任何给定解决方案,但它们从根本上做同样的事情(然后添加铃声和口哨声)
所以基本方法是:
e.g。
keyphraseID:1个关键词:“快速的棕色狐狸”
wordID:1字:
wordID:2 Word:quick
mapID:1 keyphraseID:1 wordID:1位置:1
mapID:2 keyphraseID:1 wordID:2 position:2
现在你有一个基本的逆索引,并且通过在单词列上放置一个唯一索引 - 你可以避免全表扫描。
模糊/拼写调整可以通过包括诸如Levenshtein距离,soundex或潜在语义索引之类的东西来添加 - 很大程度上取决于你正在做什么,有很多研究可用于此。
编辑: -
您还可以查看词干 - 您将文字带回同一个词根,例如修复并修复了“修复”中的两个根。常见的词干算法称为porter。
答案 4 :(得分:0)
正确的方法是建立一个自动机。
Automaton(根据定义)用于识别语言的单词,在本例中是您的关键词集合。
当然,在你的情况下,它有点复杂,因为你可能有重叠的关键字,但它也没有那么不同。
所以,从纯理论的角度来看:
后者是O(n),前者可能有点棘手。
答案 5 :(得分:0)
在互联网上搜索Aho-Corasick算法。