Data structures 从字典中获取字谜列表

Data structures 从字典中获取字谜列表,data-structures,hash,anagram,Data Structures,Hash,Anagram,基本上,字谜就像字符串的排列。例如stack,sackt,stakc都是stack的字谜(虽然上面的单词没有意义)。不管怎样,你本可以理解我的基本意思 现在,我想要一个字谜列表,给定一百万个单词,或者简单地从字典中说 我的基本问题是在字典中查找唯一字谜的总数? 分类比较 不会起作用,因为它的时间复杂性非常糟糕 我想过使用哈希表,字符串作为键 但问题是哈希函数应该是什么?如果有一些伪代码 假如一些比上述方法更好的其他方法也会有所帮助 谢谢。一个可能的哈希函数可以是(假设只有英语单词)每个字母出现次

基本上,字谜就像字符串的排列。例如
stack
sackt
stakc
都是
stack
的字谜(虽然上面的单词没有意义)。不管怎样,你本可以理解我的基本意思

现在,我想要一个
字谜
列表,给定一百万个单词,或者简单地从字典中说

我的基本问题是
在字典中查找唯一字谜的总数?

分类比较 不会起作用,因为它的时间复杂性非常糟糕

我想过使用哈希表,字符串作为键

但问题是哈希函数应该是什么?如果有一些伪代码 假如一些比上述方法更好的其他方法也会有所帮助


谢谢。

一个可能的哈希函数可以是(假设只有英语单词)每个字母出现次数的排序计数。所以对于“字谜”,你会生成[('a',3),('g',1),('n',1),('m',1),('r',1)]

或者,您可以通过从字生成位掩码来获得不精确的分组,其中对于位0-25,每个位表示该字母的存在或不存在(位0表示“a”到位25表示“z”)。但是,您必须进行更多的处理,进一步分割每个散列组,以区分例如“to”和“too”

这两种想法有帮助吗?考虑到任何特定的实现语言(我可以做C++、Python或Scala)? 编辑:添加了一些示例Scala代码和输出:

好的:我现在处于Scala模式,所以我已经做了一些事情来满足您的要求,但是(嗯哼)如果您对Scala或函数式编程不太熟悉,可能还不太清楚

使用此处列出的大量英语单词:

我在他们身上运行了这段Scala代码(在脚本模式下使用Scala 2.9大约需要5秒钟,包括编译时间,字典大约有40000个单词。这不是最有效的代码,而是我想到的第一件事)

//从单词到字母计数排序列表的哈希函数
def toHash(b:String)=b.groupBy(x=>x).map(v=>(v.\u 1,v.\u 2.size)).toList.sortWith(\u.\u 1<\u 1)
//读取文件中的所有单词,每行一个单词
val lines=scala.io.Source.fromFile(“2of12.txt”).getLines
//从单词列表转到单词列表(散列单词,单词)
val hashed=lines.map(l=>(toHash(l),l)).toList
//按散列将所有单词分组(因此将所有字谜组合在一起)
val grouped=hash.groupBy(x=>x.\u 1.map(els=>(els.\u 1,els.\u 2.map(\u.\u 2)))
//对合成的字谜集进行排序,使最大的字谜集排在第一位
val sorted=grouped.toList.sortWith(u.\u 2.size>u.\u 2.size)
为(套)
排序和比较不起作用,因为它的时间复杂度非常差

将时间复杂度交换为额外内存,只需将单词中字母的计数存储在26-
字符中(或使用任何语言的等效字符,假设您使用的是罗马字母表和字母字符),然后对数组进行散列。您必须使用O(n)相对于单词长度而言,时间是有限的,但大多数英语单词实际上并没有那么长

e、 g.
stack
sackt
stakc
都将有一个数组,其中
s
t
a
c
k
==1,其余的位置都设置为0



根据你的评论,这意味着你确实可以对一个单词的字符进行排序,只要你没有对单词本身进行排序,你可以做一些比Alex的答案更简单的事情,只需对单词字符串中的字符进行排序并对结果进行散列(larsmans先说了,但没有将其作为答案发布,所以…)

如果对每个字符的哈希代码值进行异或运算,然后按输入长度对结果进行异或运算,则无论单词的顺序如何,都会得到相同的值,这意味着所有的字谜将产生相同的哈希值。(按长度进行XORing可防止'boss'和'bo'返回相同的值,因为's'对其自身的哈希值始终为0。)

例如:

int AnagramHash(string input)
{
    int output = 0;

    foreach(char c in input)
        output ^= c.GetHashCode();

    return output ^ input.Length;
}

您仍然需要搜索具有相同AnagramHash的所有单词。我将使用哈希字段更新字典表(无论您的算法如何),以减少总体计算

编辑:
另外,作为旁注,XOR是ALU执行的最简单的操作,因此如果您最终使用它,您应该能够相当快地生成哈希。

显而易见的解决方案是将每个字符映射到一个素数并乘以素数。因此,如果'a'->2和'b'->3,则

  • ‘ab’->6
  • ‘ba’->6
  • ‘bab’->18
  • “阿巴”->36
  • ‘爸爸’->36
为了尽量减少溢出的可能性,可以将最小的素数分配给更频繁的字母(e、t、i、a、n)。注:第26个素数是101

更新:

使用以字符串作为键、以列表(字符串)作为值的哈希映射,其中字符串列表包含键字符串的所有字谜

这个问题类似于“在文件中查找单词的所有字谜”


在此处查看算法和代码问题不太清楚。你能重新表述一下目标吗?你的意思是:我有一本100万单词的词典,我希望识别词典中所有相互拼音的单词集?例如,如果词典包含:[tap,pat,pot,top]你希望看到[[tap,pat],[pot,top]]?是的@Alex。我只是想知道有多少不同的字谜?@NicholasDiPiazza希望,我的目标对你来说是清楚的。排序是这里的解决方案,如果你假设单词长度的某个恒定上限,它的复杂性是线性的。你只需对正确的东西进行排序;字符,而不是单词。基本上,我关心的是时间复杂性泰,再看看另一个答案。我想它能解决这两个复杂问题。谢谢,但你说你不想分类,