C++ 从日志文件中查找最常见的字符串

C++ 从日志文件中查找最常见的字符串,c++,c,data-structures,C++,C,Data Structures,我想在一个巨大的日志文件中找到最常见的字符串。有人能帮我怎么做吗。一种方法是对每个字符串进行散列,并计算最大值,但效率不高。有没有更好的办法 谢谢和问候 Mousey.如果“string”指的是“word”,那么我能想到的最有效的方法是在阅读时对重复的单词进行计数,而不是存储然后计数。如果string指的是line,那么在任何类似unix的shell上,您应该能够执行以下操作: sort logfile.txt | uniq -c 这假定您在每一行上没有真正唯一的东西,比如时间戳,并且文件足够

我想在一个巨大的日志文件中找到最常见的字符串。有人能帮我怎么做吗。一种方法是对每个字符串进行散列,并计算最大值,但效率不高。有没有更好的办法

谢谢和问候


Mousey.

如果“string”指的是“word”,那么我能想到的最有效的方法是在阅读时对重复的单词进行计数,而不是存储然后计数。

如果string指的是line,那么在任何类似unix的shell上,您应该能够执行以下操作:

sort logfile.txt | uniq -c
这假定您在每一行上没有真正唯一的东西,比如时间戳,并且文件足够小,可以以这种方式进行合理处理


当然,这并不使用C或C++“直接”,但是如果工具本身可能被编码在其中之一,那么它应该计数:-/p>< p>假设你是按行或按单词(或者有其他定界符),你可以通过,取每个“字符串”并把它放入数据结构中。每次再次找到相同的字符串时,都会在数据结构中增加该字符串的值


stl地图将能够做到这一点。字符串将是键,与键关联的值将是找到该字符串的次数。也可以使用stl multiset。您只需计算具有相同键的项数。

除非哈希算法很昂贵(我一直认为它们很便宜),否则哈希不是既能节省内存(平均哈希长度可能比平均行或字长度短,以字节为单位,假设为8位ASCII),又能更快地查找字典吗


不想使用散列的原因是什么?

我认为最好的方法是进行一次扫描,对单词进行计数,然后在地图中逐字累加计数


如果您的日志文件使用的是特定语言,您可能希望忽略诸如“the”、“a”之类的常用词。您可能还想合并一个。

如果您正在讨论日志文件中的任何随机子字符串,那么这个问题在多项式时间内是无法解决的。。如果它确实是一个巨大的日志文件,我相信你是索尔

但是,如果您正在谈论文件中的任何特定单词,则必须重新计算单词。这需要某种地图


如果您正在谈论文件中的任何特定行,则必须对行进行ref计数。这需要某种地图


无论哪种方式,您都需要使用某种类型的引用计数。

如果性能至关重要,您可能需要查看或


如果您只是想知道其中一个字符串是否出现超过50%的时间(让我们称该字符串为多数字符串),您可以这样做(看看我是否能正确处理):

  • 获取第一个字符串并假设它是多数字符串,并将其出现计数设置为1

  • 获取下一个字符串

  • 如果它与当前多数候选人增量相同,则它的发生计数

  • 否则,减少发生次数

  • 如果出现次数达到0,则用当前字符串替换多数候选项

  • 只要有字符串要读,就从2开始重复

  • 如果最后出现次数大于0,则重新扫描日志并计算候选项的实际出现次数,以检查它是否确实是多数字符串

    所以你得把日志翻两遍


  • 注意:这是不久前ACM编程竞赛中使用的一个问题,可用。

    可能是因为我的答案不完全正确。但是perl就是为了这些目的而设计的。在perl中,这非常容易。大多数情况下,perl代码都可以在六行内完成。

    有多大?什么是“字符串”Unix命令行工具非常好

    tr -s ' \011' '\012' < /var/log/messages | sort | uniq -c | sort -rn | head -20
    

    在编写和调试C程序所需的时间内,您可以运行大量的shell脚本。

    如何在不存储哈希的情况下运行它?您是假设整个文件都缓冲在内存中,还是每次迭代都返回磁盘?在你的方法中,你仍然需要保留一个已经统计过的单词列表,不是吗?你知道这个的实现吗?仅仅是技术就足够了,这里就有实际的源代码:哦,上帝,不要重复搜索字符串。这项技术的性能将非常糟糕。@Stefan我认识到这一点--(我自己永远不会实现这种技术)。然而,Mousey的帖子似乎并没有表明他在寻找性能。这不是粗鲁的,但“一种方法是对每个字符串进行散列,并计算最大值,但这不是有效的。有没有更好的方法可以做到这一点。”我假设更好意味着更有效,正如他所说,由于efficiency@Stefan很抱歉,当我读到最初的帖子时,我以为他说他不能使用哈希,但没有说明原因。我现在明白了,我看错了,修改了我的答案。我看不到任何其他方法可以计算每个单词,并将单词和计数器放入列表中。如果结构变得太大,你可能会考虑把你的文件分成小块,做计数并做第二轮咨询,为什么我们必须问每个Don问题是作业吗?走开。@greg这不是家庭作业。我现在不在任何学校。50%是一个很大的假设,我想知道是否有可能以某种方式将该方法调整为任意百分比(使用更多的空间)。@Matthieu M:问题中使用的定义是:“N个数的非空序列的多数数正是序列中出现N/2次以上的数。“超过50%”只是我试图记住它…这是一个非常大的假设,但据我所知,这是在线性时间内得到答案的唯一方法(你会看穿lo中的单词)
        786 --
        635 labrador
        635 Jun
        393 MARK
        236 kernel:
        163 17
        153 usb
        136 22
        118 21
        113 USB
         74 device
         73 20
         73 19
         72 18
         57 5-1:
         51 address
         43 speed
         36 New
         34 0
         33 using