我想实现一个带有键和值的sortedMap,以便通过提供一些子序列来搜索键。例如,地图包含3个条目:
abcd -> obj1
def -> obj2
abccd -> obj3
对于查询ac
,结果应该是包含第1和第3个条目的子图,但对于查询acc
,只应返回第3个条目。
我应该在内部使用什么样的数据结构来有效地返回这样的子图?例如,Treemap
将密钥存储在树(trie)中,以便根据前缀有效地返回子图?
答案 0 :(得分:1)
总结一下我在评论中所写的内容,我将其如下:
HashMap
[2-char子序列 - >单词列表]。如果查询包含一个字符,则执行完整扫描。我相信这会比为单个字符创建额外的索引具有更好的空间/复杂性,尤其是当1-char查询很少时。
答案 1 :(得分:0)
注意:我的解决方案适用于查找子字符串的情况。阅读编辑。
<强>解决方案:强>
使用前缀数据结构:http://en.wikipedia.org/wiki/Trie
您需要存储:
abcd -> obj1
为:
abcd -> obj1
bcd -> obj1
cd -> obj1
d -> obj1
为了找到你的结果,你将在trie中足够深入以满足条件和DFS从那里找到所有可能的解决方案。
<强>示例:强>
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。之后我们会DFS。我们已经在obj2,如果我们在obj1移动角色e。因此,我们可以通过条目d获得它们。
cd
首先我们移动角色c然后移动角色d。现在我们DFS和我们唯一可以找到的路径是添加导致obj1的字符e。
efg
Trie中没有满足条件的路径,因此我们没有解决方案。
修改强>
如果我们要查找原始元素的子字符串,我的解决方案就有效。要修改我的解决方案以使其适用于任何非传染性子字符串,您必须在Trie中插入所有排列。
答案 2 :(得分:0)
你的&#34;字符&#34;可以解释为传统搜索引擎AND查询中的术语。
来自此评论:
abcd的所有子序列,例如a,b,c,d,ab,ac,ad,bc,bd,cd, abc,abd,acd,abcd等,查询时,应返回子图 abcd - &gt; obj1作为其入口之一。
我们可以解释一下,使用带有Aspid Beaver Cherokee Deer(ABCD)术语的文档时,应该在搜索任何单词或其任何组合时返回该文档。
您要为此构建的是inverted index。有关详细信息,请参阅this answer。从本质上讲,你会为每个&#34;字符&#34;构建一个HashMap
或查找表(没有那么多的字符)。 (= term 在search-engine-speak中),其中查找将返回它出现的所有objX
(= document 在search-engine-speak中),理想情况下按升序排列。
要查找与一组字符关联的所有对象,您可以加入每个字符的集合。由于它们是有序的,因此您可以在线性时间内计算集合交点。
如果查询ba
不与abc
键匹配,则可以优化查找表/ HashMap
以存储字符位置(例如: store&#34; b在Obj1中位于0&#34;,&#34; a在Obj1中找到位置1&#34;而不是丢弃位置)。在计算搜索交叉时,您将按搜索顺序继续并丢弃具有不正确相对顺序的匹配。
这是搜索引擎的惯例,并且已经在性能方面进行了详尽的分析。
编辑:效果
如果不同的&#34;术语的数量&#34;很低(例如:26个小写英文字母)你可以通过添加n-gram作为术语来加快速度(其中,对于&#34; abc&#34;,你要添加&#34; a&#34;,& #34; b&#34;,&#34; c&#34;,&#34; ab&#34;,&#34; ac&#34;,&#34; bc&#34;,&#34; abc& #34)。相同的规则将适用 - 搜索量减半,并且由于预期会出现重叠,因此可以使用Sasha的技巧来避免存储索引。
答案 3 :(得分:0)
您可以尝试使用通配符进行aho-corasick。 Aho-Corasick是更快的多模式匹配算法,并且通过通配符可以给出所有子串。您可以在codeplex(https://phpahocorasick.codeplex.com)上尝试我的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");
答案 4 :(得分:0)
/**
* @author viborole
*
*/
public class SortedMapSubsequence {
/**
* @param args
*/
public static void main(String[] args) {
Map<String, String> data = new HashMap<String,String>();
data.put("abcd", "obj1");
data.put("def", "obj2");
data.put("abccd", "obj3");
String query="acc";
search(query, data);
}
private static void search(String query, Map<String, String> data) {
for (Map.Entry<String, String> entry : data.entrySet())
{
String key=entry.getKey();
char[] k=key.toCharArray();
char[] q=query.toCharArray();
int kpos=0;
char[] found = new char[q.length];
for(int i=0;i<q.length;i++){
if(i>0){
kpos++;
}
for(int j=kpos;j<k.length;j++){
if(k[j]==q[i]){
kpos=j;
found[i]=k[j];
break;
}
}
}
if(Arrays.equals(found,q)){
System.out.println("found : "+ entry.getValue());
}
}
}
}