将字典中的子字符串与其他字符串匹配:建议?

时间:2010-01-06 15:30:26

标签: java nlp

Hellow Stack Overflow人。我想对以下问题提出一些建议。我正在使用Java。

我有一个带有多个字符串的数组#1。例如,两个字符串可能是:“苹果落在牛顿头上”和“苹果在树上生长”。

另一方面,我有另一个阵列#2,其中的术语如(Fruits => Apple,Orange,Peach; Items => Pen,Book; ...)。我把这个数组称为我的“字典”。

通过比较一个阵列到另一个阵列的项目,我需要看到#1中的项目从#2落入哪个“类别”。例如。来自#1的两者都属于“水果”。

我最重要的考虑因素是速度。我需要快速完成这些操作。允许恒定时间检索的结构将是好的。

我使用contains()方法考虑了Hashset,但它不允许使用子字符串。我也尝试运行像(apple | orange | peach | ...等)的正则表达式,并且不区分大小写的标志,但我读到,当条款数量增加时,它将不会很快(预期最小值为200)。最后,我搜索了,并考虑使用带有indexOf()的ArrayList,但我不知道它的性能。我还需要知道哪些术语实际匹配,所以在这种情况下,它将是“Apple”。

请提供您对此问题的看法,想法和建议。

我看到了Aho-Corasick算法,但关键字/术语很可能经常发生变化。所以我认为我不能使用它。哦,我不是文本挖掘和数学的专家,所以请详细说明复杂的概念。

谢谢你,Stack Overflow人,你的时间! :)

3 个答案:

答案 0 :(得分:3)

如果您使用Google Collections中的多重地图,则他们可以使用地图反转地图(因此您可以使用{“Fruits”=> [Apple]}这样的地图开始,然后生成一张带有{“Apple”的地图=> [“Fruits”]}。所以你可以在一次调用地图时查找单词并找到它的类别列表。

我希望自己能够自己拆分字符串并一次一个地查找地图中的单词,这样我就可以进行词干(调整不同的单词结尾)和停用词过滤。使用地图应该可以获得良好的查找时间,而且很容易尝试。

答案 1 :(得分:2)

suffix tree或类似的数据结构是否适用于您的应用程序?它提供了O(m)字符串查找,其中m是搜索字符串的长度,在O(n 2 )之后 - 或者更好地使用一些技巧 - 初始设置,并且,还有一些额外的努力,您可以将任意数据(例如对类别的引用)与词典中的完整单词相关联。如果您不想自己编写代码,我相信BioJava库包含一个实现。

您也可以在初始设置后将字符串添加到后缀树,但成本仍然在O(n 2 )附近。如果你要添加简短的话,这可能不是什么大问题。

答案 2 :(得分:0)

如果您只需要查找200个术语,则regexp可能实际上适合您。当然正则表达式很大,但如果你编译一次并且只使用这个编译的模式,查找时间可能是数组#1中所有字符串的总长度的线性,我看不出你怎么希望被存在比这更好。

因此算法将:将要查找的数组#2的单词连接到正则表达式中,编译它,然后在数组#1中找到匹配项。

(正则表达式被编译成一个状态机 - 在字符串的每个字符上它只是为下一个状态进行表查找。如果正则表达式很复杂,你可能有回溯会增加时间,但你的常规表达式的结构非常简单。)