假设我们有一个约250,000字的字典。算法应该将12个字母作为数组或字符串,并找到与字典中最长单词匹配的变体。
当然,人们总是可以蛮力,但我想知道最优雅的做法是什么?
如果不使用任何语言特定功能作为主要问题的快捷方式,也可以接受使用PHP以外的语言的答案。
注意:单词存储在数据库中,但我可以将它们拉入内存以提高速度。虽然我不确定PHP的索引是否比MySQL数据库更好?
答案 0 :(得分:4)
对于字典中的每个单词,按字母顺序对字母进行排序。所以“foobar”变成“abfoor”。
从完整输入开始,按字母顺序排序。如果找不到,请删除一个字母,然后再次进行搜索。每封信都这样做。然后删除两个字母......依此类推。
最坏情况:根本找不到'anagram'。您将必须测试所有可能的输入组合,这将为您提供大约2 ^ n个查找,其中n是输入字符的数量(在您的示例中:12) 但是,算法的速度并不取决于运行时字典的大小(当然,按字母顺序对单词进行排序),在我看来这是最重要的事情。
答案 1 :(得分:4)
您应该计算每个单词的签名,只需执行一次,然后将其与单词一起保存到数据库中。
表格应该是这样的:
word varchar(12),
a int,
b int,
c int,
...
w int,
z int;
并且a到z的字段必须包含单词中包含的字母数, 例如anagram会有一个像以下的记录:
word, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
anagram, 3,0,0,0,0,0,1,0,0,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0
一旦你有十二个字母,你必须计算集合的签名并使用它 创建一个像这样的选择:
select word, length(word) as wordlen
from dictionary
where
a <= 4 and
b <= 0 and
c <= 1 and
d <= 2 and
e <= 0 and
f <= 0 and
....
z <= 0
order by wordlen desc;
为了拥有可以使用你设置的字母集创建的所有单词。
没有排列,没有组合,虽然工作(编译字典)已经完成 只有一次离线。
只是另一个提示,从数据库中删除所有超过十二个字符的单词
答案 2 :(得分:1)
如果你想找到最长的匹配单词,我会先尝试按字长对单词进行排序,这样你就可以把最大的精力放在最长的单词上
答案 3 :(得分:1)
Eric Lippert写了一篇关于字谜搜索的信息blog post。这些示例都使用c#,但这些技术可用于任何语言。
在字典中有效搜索字谜的技巧是要意识到所有字谜都有相同的字母,只是顺序不同。如果你“标准化”每个单词,使其字母大写并按字母顺序排列,那么检查一个单词是否是另一个单词的字谜就像比较它们的规范形式一样简单
使用这种技术,您可以轻松地从哈希表或平衡树中查找字谜。
答案 4 :(得分:0)
我的想法:
伪代码:
int_32 letter_mask
int_32 permutation_match_mask
if(((letter_mask XOR permutation_match_mask) AND letter_mask) == 0)
YOU_HAVE_HIT;
当你在字母掩码中有非重复字母时,这是有效的,但如果你有更多的字母(你可能有),那么你可以扩展leter和permutationmatchmask
修改
另一个想法
按字母顺序对词汇中的单词进行排序。
如果有12个letteres并且它们全部不同,那么正好有4095个可能的组合(只有sum i = 1-> 12个二项式(12个i))(对于字母ABCD,有(ABCD,ABC) ,ABD,ACD,BCD,AB,AC,AD,BC,BD,CD,A,B,C,D)正如我所说,有12个不同的字母有4095个,如果有些字母相同则更少。
复杂性4095 * Log2(250000)什么是aproximetly 75000.那么值得尝试。
针对每种组合进行精确搜索。