C 计算长字符串中的唯一单词数

C 计算长字符串中的唯一单词数,c,string,algorithm,C,String,Algorithm,假设我有一整本(或两本)的书在记忆中,我想数一数其中独特的单词数,我该如何数一数?我对小字符串的天真做法是: create a simple hash, place it in array of fixed size, increment array element All words for which hash array has 1 in it, are unique. 我想要一个更好的方法来处理我的很长的字符串。我是用C语言编写代码的。我认为一种方法是使用工作线程,这些线程在块中工作并

假设我有一整本(或两本)的书在记忆中,我想数一数其中独特的单词数,我该如何数一数?我对小字符串的天真做法是:

create a simple hash, place it in array of fixed size, increment array element
All words for which hash array has 1 in it, are unique.

我想要一个更好的方法来处理我的很长的字符串。我是用C语言编写代码的。我认为一种方法是使用工作线程,这些线程在块中工作并合并结果。有更好的算法吗?

正如@user3386109已经提到的,Trie将是最佳解决方案。其基本思想是创建一棵人物树。例如:

                             a
                            / \
                           /   \
                          b     c
                         /     / \
                        /     /   \
                       d     a     b
将包含“a”、“ab”、“abd”、“ac”、“aca”和“acb”等字样。只需将该方法扩展到一个树形图,将每个单词映射到其对应的计数,整个查找就会变成线性的,并且可以并行地遍历单词:

trie lookup
trienode node = lookup.root

for char c in input:
    if c == ' ':
        //end of word, increment count
        node.count += 1

        //start with root again
        node = lookup.root
    else:
        //go to matching node in the trie
        if !node.hasChild(c)
            node.insertChild(c)

        node = node.childForChar(c)

if node != lookup.root
     //increment count for last word, if the last char wasn't a space
    node.count += 1
现在只需要分析用这种方法构造的trie。这可以通过简单地筛选计数大于0的所有节点并列出这些节点的路径及其各自的计数来轻松完成

您可能需要为标点符号、数字等添加筛选。但是,如果对子节点的查找设计正确,这种方法可以扫描
O(n)
中的整个文本,即使对于子节点的查找表使用
HashTree
,查找仍然可以在对数时间内执行,从而导致
O(n log n)
,其中
n
是输入文本的长度(输入文本中的字符)


多亏@PaulHankin做了一个基准测试。结果基本上是:根据我们对输入字母表的限制程度,
Trie
HashTable
工作得更好(正如@PaulHankin所建议的),或性能更差。如果将输入限制为小写字母,则trie的性能比
哈希表
好2.6倍,如果我们允许所有256个ASCII字符并将数组用作查找表,则性能将降低到
哈希表
性能的1.3倍。将
哈希表
用作子节点的loup表将进一步降低将
Trie
的性能提高到运行时的2倍,这是一种利用
哈希表的算法。因此,毕竟,该算法的速度实际上取决于您愿意限制输入字母表大小的程度。

使用Hadoop!您能展示您目前拥有的代码吗?如果您你问的是一个特定的问题,而不是一般的、开放的问题?只有当你有多个可用的处理器并且使算法变得非常复杂时,多线程才会有帮助。尽管如此,不管你如何分解它,一些代码需要遍历每一个单词。你简单、直接的方法似乎是合理的,但我不会告诉我们e一个固定大小的数组,因为你可能会耗尽空间。很确定这是发明的解决问题。总是喜欢那些向下的投票,而不给出理由……不管怎样,我犯了什么错误?@user3386109 sry,意思是
O(n)
。以及
O(n*m)的复杂性
n
作为字数,以
m
作为平均字长,相当于
O(c)
其中
c
是输入文本中的字符数。是的,你是对的。我是从字数的角度考虑的,以便与作用于字而不是字符的其他数据结构进行比较。trie的性能很可能比哈希表差得多,占用的内存是哈希表的数倍。同时,还可以重复使用节点前缀是共享的,每个节点(和/或哈希表)中所需的许多指针的成本非常难以克服,并将导致可怕的内存局部性。@PaulHankin我对此表示怀疑。如果子查找实现正确,一个好的哈希函数本身将比trie中的整个查找消耗更多的运行时间。尽管如此,正如我已经说过的,内存效率是可怕的。但是由于OP所说的对于两本书或类似的东西,trie的内存效率不会那么差,与将要分析的数据量相比,trie不会具有那么大的权重。哈希表本身很可能会经历大量冲突,从而导致性能损失。