Java 实现子序列匹配的sortedMap
我想实现一个带有键和值的sortedMap,这样就可以通过提供一些子序列来搜索键。例如,地图包含3个条目:Java 实现子序列匹配的sortedMap,java,dictionary,data-structures,treemap,sortedmap,Java,Dictionary,Data Structures,Treemap,Sortedmap,我想实现一个带有键和值的sortedMap,这样就可以通过提供一些子序列来搜索键。例如,地图包含3个条目: abcd -> obj1 def -> obj2 abccd -> obj3 对于查询ac,结果应该是包含第一个和第三个条目的子映射,但是对于查询acc,只应该返回第三个条目 我应该在内部使用什么样的数据结构来高效地返回这样的子映射?例如,Treemap将密钥存储在树(trie)中,以根据前缀有效地返回submap?注意:我的解决方案在查找子字符串时有效。阅读编辑 解决
abcd -> obj1
def -> obj2
abccd -> obj3
对于查询ac
,结果应该是包含第一个和第三个条目的子映射,但是对于查询acc
,只应该返回第三个条目
我应该在内部使用什么样的数据结构来高效地返回这样的子映射?例如,
Treemap
将密钥存储在树(trie)中,以根据前缀有效地返回submap?注意:我的解决方案在查找子字符串时有效。阅读编辑
解决方案:
ab -> obj1
cde -> obj1
bad -> obj2
使用前缀数据结构:
您需要存储:
abcd -> obj1
作为:
为了找到您的结果,您需要深入到trie中,以满足条件,并从那里找到所有可能的解决方案
示例:
ab -> obj1
cde -> obj1
bad -> obj2
我们将在Trie中插入以下条目:
ab -> obj1
b -> obj1
cde -> obj1
de -> obj1
e -> obj1
bad -> obj2
ad -> obj2
d -> obj2
现在想象一下我们在寻找下一个条目:
d
Trie中字符d的第一个下移。在那之后,我们将继续。我们已经在obj2,如果我们在obj1移动字符e。所以我们可以用条目d得到它们
cd
首先我们移动字符c,然后移动字符d。现在我们看到DFS,我们能找到的唯一路径是添加字符e,这将导致obj1
efg
Trie中没有满足out条件的路径,因此我们得不到解
编辑:
ab -> obj1
cde -> obj1
bad -> obj2
如果我们正在寻找原始元素的子字符串,我的解决方案是有效的。要修改我的解决方案,使其适用于任何非传染性子字符串,您必须在Trie中插入所有置换 您的“字符”可以在传统的搜索引擎和查询中解释为术语
根据这一评论:
abcd的所有子序列,如a、b、c、d、ab、ac、ad、bc、bd、cd、,
abc、abd、acd、abcd等在查询时应返回带有
abcd->obj1作为其条目之一
我们可以解释为,如果文档中有Aspid Beaver Cherokee Deer(ABCD)一词,则在搜索该文档中的任一词或其任何组合时,都应返回该文档
您要为此构建的是一个。有关更多详细信息,请参阅。基本上,您将为每个“字符”(=搜索引擎语音中的术语)构建一个哈希映射或查找表(没有那么多字符),其中查找将以升序返回所有出现(=搜索引擎语音中的文档)的objX
若要查找与一组字符关联的所有对象,请将每个字符的集合合并。因为它们是有序的,所以可以在线性时间内计算集合交点
如果查询ba
不应与abc
键匹配,则可以优化查找表/HashMap
以存储字符位置(例如:存储“在位置0的Obj1中找到b”,“在位置1的Obj1中找到a”,而不是丢弃位置)。计算搜索交集时,您将按搜索顺序进行,并放弃具有错误相对顺序的匹配
这是搜索引擎的常规操作,已经从性能方面进行了详尽的分析
编辑:性能
如果不同的“术语”数量较少(例如:26个小写英文字母),您可以通过添加n-gram作为术语(其中,对于“abc”,您可以添加“a”、“b”、“c”、“ab”、“ac”、“bc”和“abc”)来加快这一速度。同样的规则也适用于一半的搜索,而且由于预期会出现重叠,因此可以使用Sasha的技巧来避免存储索引。为了总结我在评论中写的内容,我将如下所示:
使用条目[2字符子序列->单词列表]创建附加索引HashMap
添加时:从给定单词生成所有不同的2字符子序列,将该单词添加到索引映射的每个对应条目中
查询:从一个查询中生成所有不同的2字符子序列,其中找到一个对应于索引映射中最短列表的子序列,获取该列表。按完整查询对其进行过滤,并从主映射中收集相应的值
如果查询由一个字符组成,则执行完全扫描。我相信这会比为单个字符创建额外的索引具有更好的空间/复杂性,尤其是当单字符查询很少时。您可以尝试使用带有通配符的aho-corasick。Aho Corasick是一种更快的多模式匹配算法,它使用通配符提供所有子字符串。您可以在codeplex()上尝试我的php实现。例如,对基因模式使用通配符的单元测试:
$tree = new Ahocorasick\Ahocorasick();
$tree->add("AC");
$tree->add("GTG");
$tree->add("AACT");
echo $tree->match("ACCGAGTGCGTGGACAAACTACGATTGTGGAATGAACT","AC*GT");
$this->expectOutputString("ACCGAGT,ACCGAGTGCGT,ACCGAGTGCGTGGACAAACTACGATTGT,ACAAACTACGATTGT,ACTACGATTGT,ACGATTGT");
/**
*@作者viborole
*
*/
公共类排序的子序列{
/**
*@param args
*/
公共静态void main(字符串[]args){
映射数据=新的HashMap();
数据输入(“abcd”、“obj1”);
数据输入(“def”、“obj2”);
数据。put(“abccd”、“obj3”);
字符串query=“acc”;
搜索(查询、数据);
}
私有静态无效搜索(字符串查询、地图数据){
for(Map.Entry:data.entrySet())
{
String key=entry.getKey();
char[]k=key.toCharArray();
char[]q=query.toCharArray();
int kpos=0;
char[]found=新字符[q.length];
对于(int i=0;i0){
kpos++;
}
对于(int j=kpos;jfor querybc
,您的地图是否应该返回第一个和第三个条目?对于查询“ca”它应该返回第一个和第三个条目吗?还是不返回?@stephen..我为我的英语不好道歉,我的意思是,abcd的所有子序列,例如a、b、c、d、ab、ac、ad、bc、bd、cd、abc、abd、acd、abcd等,当被查询时,应该返回一个子映射,其中包含abcd->obj1项。@lostmindda
也是ab的2字符排列cd
@我最不了解,但OP明确表示他需要保持元素的顺序,所以他需要