Erlang:这个trie实现的最大错误是什么?

Erlang:这个trie实现的最大错误是什么?,erlang,trie,Erlang,Trie,在假期里,我的家人喜欢玩拼字游戏。问题是,我对博格尔很在行。所以我做了任何一个好程序员都会做的事:写一个程序为我播放 该算法的核心是一个简单的算法,其中每个节点都是对下一个字母的引用的dict 这是trie:add实现: add([], Trie) -> dict:store(stop, true, Trie); add([Ch|Rest], Trie) -> % setdefault(Key, Default, Dict) -> % case dict:fin

在假期里,我的家人喜欢玩拼字游戏。问题是,我对博格尔很在行。所以我做了任何一个好程序员都会做的事:写一个程序为我播放

该算法的核心是一个简单的算法,其中每个节点都是对下一个字母的引用的
dict

这是
trie:add
实现:

add([], Trie) -> dict:store(stop, true, Trie); add([Ch|Rest], Trie) -> % setdefault(Key, Default, Dict) -> % case dict:find(Key, Dict) of % { ok, Val } -> { Dict, Val } % error -> { dict:new(), Default } % end. { NewTrie, SubTrie } = setdefault(Ch, dict:new(), Trie), NewSubTrie = add(Rest, SubTrie), dict:store(Ch, NewSubTrie, NewTrie). 添加([],Trie)-> dict:存储(stop、true、Trie); 添加([Ch|Rest],Trie)-> %设置默认值(键、默认值、Dict)-> %案例记录:发现(关键,记录)的 %{好的,Val}->{Dict,Val} %错误->{dict:new(),默认值} %结束。 {NewTrie,SubTrie}=setdefault(Ch,dict:new(),Trie), NewSubTrie=add(Rest,SubTrie), 目录:商店(Ch、NewSubTrie、NewTrie)。 您可以在这里看到其余部分,以及如何使用它的示例(在底部):

现在,这是我在Erlang中的第一个严肃的程序,我知道它可能有很多问题……但我最关心的是它使用了800 MB的RAM


那么,我做错了什么?我不知道你的算法,但是如果你存储了那么多数据,也许你应该考虑使用Erlang的内置有向图库来表示你的trie,而不是这么多Dict。

您只需将单词存储在ets表格中即可实现此功能:

% create table; add words
> ets:new(words, [named_table, set]).
> ets:insert(words, [{"zed"}]).  
> ets:insert(words, [{"zebra"}]).    

% check if word exists
> ets:lookup(words, "zed").          
[{"zed"}]

% check if "ze" has a continuation among the words
78> ets:match(words, {"ze" ++ '$1'}).
[["d"],["bra"]]
如果trie是必须的,但您可以使用非功能性方法,那么您可以尝试s,正如Paul已经建议的那样


如果你想保持功能性,你可以通过使用使用更少内存的结构来节省一些字节的内存,例如s或记录,例如
-record(node,{a,b,…,x,y,z})

我不记得dict需要多少内存,但让我们估计一下。您有2.5e6个字符和2e5个单词。如果您的trie根本没有共享,那么dicts中需要2.7e6个关联(每个字符和每个“停止”符号对应一个)。一个简单的纯粹功能性的dict表示可能每个关联4个单词——可能更少,但我正试图得到一个上限。在64位机器上,这需要8*4*270万字节,即86兆字节。这只是你800米的十分之一,所以这里肯定有问题


更新:用哈希表表示DICT;当你有很多非常小的dict时,这意味着很多开销,就像你做的那样。我会尝试更改您的代码以使用模块,该模块应该与我上面的计算相匹配。

如果所有单词都是英语,并且大小写都不重要,那么所有字符都可以用1到26的数字编码(事实上,在Erlang中,它们是97到122的数字),保留0以停止。因此,您也可以使用。

解决此问题的另一种方法是查看单词列表,看看是否可以从骰子构造单词。这样,您只需要很少的RAM,编写代码可能会更有趣。(优化和并发)

查看s。它们比试过的要紧凑得多。

Ha。几年前我用PHP做的。你的输入单词列表有多大?我的单词列表是200000个单词(或2.5兆)。酷-我会研究一下。谢谢。好吧,我一直在修补ets,但我一直在“糟糕的争论”中遇到问题。也许你知道一个简单的解决办法?问题就在这里:好吧,我也修改了proplist的实现。。。它遇到了一个问题,导致外壳挂起。我在这里问过这个问题:(ps:谢谢你的帮助-非常感谢)。要检查dict()构造需要多少内存,请调用:
erts\u debug:flat\u size(dict:new())
。它返回46个字,32位系统为184字节,64位系统为368字节。感谢您的建议。。。尽管我在创建基于proplist的trie时遇到了一个奇怪的问题,即shell挂起的问题,我在这里问过:-您是否有机会提供一些见解?