热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

统计分析文章中英文单词出现次数及频率(C++实现)

设计思路:1.为了统计数据具有实际意义:统计中需要剔除一些无统计意义的词,例如amisare等虚词、代词、连词等。一般的文章句首单词首字母为大写,此时需要将此类情况的大

设计思路:

1.为了统计数据具有实际意义:

<1>统计中需要剔除一些无统计意义的词,例如 am is are 等虚词、代词、连词等。

<2>一般的文章句首单词首字母为大写,此时需要将此类情况的大写字母转化为小写字母,但值得一提的是,许多专有名词入如 WHO iPhone 等词不应作此类处理。

<3>①为了应对文章总词数较少(几十个词)造成大多数单词仅仅只出现一次的情况,程序选取出现频率高于5%的词不论文章总词数取值均无条件输出。②为了应对文章词数很多(5W~50W词)造成输出序列太长,程序选取出现频率高于0.01%的词。③中等篇幅的文章,在出现频率高于0.01%的条件上加上至少出现2次的条件。

2.为了统计的高效性:

源单词集合无需统计的单词集合根据字典序进行快速排序(平均O(nlogn)),再进行顺序查找(O(n))以获得相同词的重复次数,得到的词在无需统计的单词集合中查找(O(nlogn)),只有在无需统计的单词集合中不出现才能被统计如结果集,最后对结果集以出现次数为关键字进行降序排序(O(nlogn)),输出结果。总复杂度为(O(nlogn)),测试中课瞬间完成统计10W词级别的输入量。

(如果使用红黑树的二叉检索树实现无意义词集合的维护以及最后统计结果的维护效率可能还能小幅提升,可用STL的set实现,总复杂度仍为(O(nlong)))

3.为了程序的健壮性和适用性:

<1>程序输出保持固定且较强适应性的输出格式,程序会自动过滤掉输入文件中允许任意次序穿插的符号、汉字、标点、空格等非英文字符(但不能有Unicode格式字符),此外程序尽量降低了因某些特殊情况的发生造成格式混乱的可能。

<2>在当输入文件为空时,按照统一的格式输出相应异常提示,并结束程序。

<3>由于输出条件的控制造成输出为空时,也按照统一的格式输出相应异常提示,并结束程序。

例如:当输入一个词数很多的文件(10W个词),而恰好每个词均出现了不足(100000X0.05%=10次),那么作者认为,这篇文章不具有足够的关于词汇出现次数(频率)的统计意义。

<4>对于程序的输入输出已经需要剔除的单词,程序均使用文件存放。对于输入输出较大或者需要剔除词集需要修改时,这样的IO方式能够扩大程序的适用范围。(在程序开头代码部分建立一张需要剔除词的表的做法太low了)

<5>关于如何找到需要剔除的词,若仅仅是自己陈列能想到的词,或者借助搜索引擎获取他人收集的虚词表。测试表明这样的做法遗漏较多(作者使用100W词英文小说实际测试结果显示,仍然有几十个无意义词在统计结果的前列)。因此获得虚词以及无意义词有效的方法是:输入一篇100W词及其以上单词量的文章,选取统计到的前100-150个单词复制到需要剔除的词的文件中,并检查其中包含有的有意义词重新删去即可。测试表明,此种方法获得的无意义词表十分有效,在之后的各个量级统计中均很难找到无意义的统计词被列入结果。

4.附图展示不同输入的结果:

<1>大数据量输入:《大卫.科波维尔》英文版统计结果如下:(26.7W词)(耗时:0.6080s)

《统计分析文章中英文单词出现次数及频率(C++实现)》

此处省略若干统计信息。

《统计分析文章中英文单词出现次数及频率(C++实现)》

从结果中可以看出,几乎所有的代词介词连词一类统计意义不大的词均已被剔除在外。


<2>小数据量输入:Oracle官网首页统计结果如下:(耗时:0.0030s)

《统计分析文章中英文单词出现次数及频率(C++实现)》


<3>当输入为类似单词表一样各个数据出现次数不能体现出差异并且词数较大时,作者认为这样的词集没有足够的统计意义,因此输出提示信息。

诸如以下输入:

《统计分析文章中英文单词出现次数及频率(C++实现)》

此处省略若干单词。

统计结果如下:

《统计分析文章中英文单词出现次数及频率(C++实现)》

此例子充分证明程序可自动过滤汉字标点等非英文字符,并对于没有足够统计意义的输入提供提示信息。


<4>当找不到in.txt文件过in.txt文件为空时。

《统计分析文章中英文单词出现次数及频率(C++实现)》

<5>当程序输入比较大,需要1秒甚至数秒的运算时间时,程序需要输出提示信息表示程序正在正常运行而非卡死。

此例将输入263.6W单词,文件大小12.7M。

《统计分析文章中英文单词出现次数及频率(C++实现)》

统计结果如下:

《统计分析文章中英文单词出现次数及频率(C++实现)》

5.实现代码如下:

#include
#include
#include
#include
#include
#include

using namespace std;
#define MAX_LENGTH 1<<10//单词的最大长度

typedef struct{
   string str;
   int cnt;
}word;

int number_of_words=0;//记录单词统计总数
vector virtual_word;//需要被除去的虚词集
vector raw_word;//资源文本中的单词集
vector word_statistics;//统计结果集

/*字典排序比较函数*/
bool cmp_raw_word(const string &a,const string &b){return a

/*词汇出现次数降序排序比较函数*/
bool cmp_word_statistics(const word &a,const word &b){return a.cnt>b.cnt;}

/*虚读取以处理资源文件以及虚词文件除大小写字母外的所有汉字及字符*/
bool skip(){ scanf(&#8220;%*[^a-z||A-Z]&#8221;); return true;}

int main()
{
   /*初始化时间*/
   clock_t start,finish;
   double totaltime;
   start=clock();

   printf(&#8220;Wait for a moment please.\n&#8221;);

   /*定义缓存空间*/
   word w;
   char _word[MAX_LENGTH];

   vector::iterator it,last;
   vector::iterator wit;

   /*重定向输入流至 virtual.txt 文件,读取 virtual.txt 文件所有英文单词*/
   freopen(&#8220;virtual.ini&#8221;,&#8221;r&#8221;,stdin);
   while(skip()&&scanf(&#8220;%[a-zA-Z]&#8221;,_word)!=EOF) virtual_word.push_back(_word);

   /*对虚词表进行排序以便其后的搜索操作*/
   sort(virtual_word.begin(),virtual_word.end(),cmp_raw_word);

   /*重定向输入流至 in.txt 文件,并读取 in.txt 文件中所有英文单词*/
   freopen(&#8220;in.txt&#8221;,&#8221;r&#8221;,stdin);
   while(skip()&&scanf(&#8220;%[a-zA-Z]&#8221;,_word)!=EOF)
   {
      number_of_words++;
      /*将只有首字母大写的单词的首字母转换成小写*/
      if(_word[1]!=&#8217;\0&#8217;&&isupper(_word[0])&&islower(_word[1])) _word[0]|=1<<5;
      raw_word.push_back(_word);
   }

   /*重定向输出流至 out.txt 文件并输出相关说明信息*/
   freopen(&#8220;out.txt&#8221;,&#8221;w&#8221;,stdout);
   printf(&#8220;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;\n&#8221;);
   printf(&#8220;%d words be counted! \nDetails are as follow:\n&#8221;,number_of_words);
   printf(&#8220;no.   word              time          frequency\n&#8221;);
   printf(&#8220;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;\n&#8221;);

   /*若没有检测到输入时,结束程序并返回提示信息*/
   if(!raw_word.size())
   {
      printf(&#8220;There is no word in the \&#8221;in.txt\&#8221; or \&#8221;in.txt\&#8221; inexistence!\n&#8221;);
      printf(&#8220;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;\n&#8221;);
      return 0;
   }

   /*对单词集进行字典排序以便进行出现次数统计操作*/
   sort(raw_word.begin(),raw_word.end(),cmp_raw_word);
   for(last=raw_word.begin(),it=raw_word.begin()+1;it!=raw_word.end();it++)
   {
      if(*it!=*last)
      {
         w.str=*last;
         w.cnt=it-last;
         /*得到的统计结果在 virtual_word 集合中验证,未在 virtual_word 集合中出现才计入结果*/
         if(!binary_search(virtual_word.begin(),virtual_word.end(),*last)) word_statistics.push_back(w);
         last=it;
      }
   }

   /*弥补跳出循环时最后一个未被计入单词*/
   w.str=*last;
   w.cnt=it-last;
   if(!binary_search(virtual_word.begin(),virtual_word.end(),*last)) word_statistics.push_back(w);

   /*对结果集进行出现次数关键词降序排序*/
   sort(word_statistics.begin(),word_statistics.end(),cmp_word_statistics);
   bool b=false;
   for(wit=word_statistics.begin();wit!=word_statistics.end();wit++)
   {
      /*为保证统计有意义,对统计数据输出进行调节*/
      if((*wit).cnt*1.0/number_of_words>=0.05||((*wit).cnt>=2&&(*wit).cnt*100.0/number_of_words>=0.01)){
          printf(&#8220;%-5d %-16s %5d %17.3lf%%\n&#8221;,wit-word_statistics.begin()+1,((*wit).str).c_str(),(*wit).cnt,(*wit).cnt*100.0/number_of_words);
          b=true;
      }
   }

   /*因统计数据输出调节引起的空输出提示*/
   if(!b)printf(&#8220;no appropriate word!\n&#8221;);
   printf(&#8220;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;\n&#8221;);

   /*计算并输出统计程序消耗的时间*/
   finish=clock();
   totaltime=(double)(finish-start)/CLOCKS_PER_SEC;
   printf(&#8220;The program cost %.4lf second(s)&#8221;,totaltime);
   return 0;
}


推荐阅读
  • 本文介绍了操作系统的定义和功能,包括操作系统的本质、用户界面以及系统调用的分类。同时还介绍了进程和线程的区别,包括进程和线程的定义和作用。 ... [详细]
  • 阿里Treebased Deep Match(TDM) 学习笔记及技术发展回顾
    本文介绍了阿里Treebased Deep Match(TDM)的学习笔记,同时回顾了工业界技术发展的几代演进。从基于统计的启发式规则方法到基于内积模型的向量检索方法,再到引入复杂深度学习模型的下一代匹配技术。文章详细解释了基于统计的启发式规则方法和基于内积模型的向量检索方法的原理和应用,并介绍了TDM的背景和优势。最后,文章提到了向量距离和基于向量聚类的索引结构对于加速匹配效率的作用。本文对于理解TDM的学习过程和了解匹配技术的发展具有重要意义。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • c语言\n不换行,c语言printf不换行
    本文目录一览:1、C语言不换行输入2、c语言的 ... [详细]
  • 本文介绍了为什么要使用多进程处理TCP服务端,多进程的好处包括可靠性高和处理大量数据时速度快。然而,多进程不能共享进程空间,因此有一些变量不能共享。文章还提供了使用多进程实现TCP服务端的代码,并对代码进行了详细注释。 ... [详细]
  • 本文介绍了解决二叉树层序创建问题的方法。通过使用队列结构体和二叉树结构体,实现了入队和出队操作,并提供了判断队列是否为空的函数。详细介绍了解决该问题的步骤和流程。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 3.223.28周学习总结中的贪心作业收获及困惑
    本文是对3.223.28周学习总结中的贪心作业进行总结,作者在解题过程中参考了他人的代码,但前提是要先理解题目并有解题思路。作者分享了自己在贪心作业中的收获,同时提到了一道让他困惑的题目,即input details部分引发的疑惑。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 本文介绍了最长上升子序列问题的一个变种解法,通过记录拐点的位置,将问题拆分为左右两个LIS问题。详细讲解了算法的实现过程,并给出了相应的代码。 ... [详细]
  • Ihavethefollowingonhtml我在html上有以下内容<html><head><scriptsrc..3003_Tes ... [详细]
  • 李逍遥寻找仙药的迷阵之旅
    本文讲述了少年李逍遥为了救治婶婶的病情,前往仙灵岛寻找仙药的故事。他需要穿越一个由M×N个方格组成的迷阵,有些方格内有怪物,有些方格是安全的。李逍遥需要避开有怪物的方格,并经过最少的方格,找到仙药。在寻找的过程中,他还会遇到神秘人物。本文提供了一个迷阵样例及李逍遥找到仙药的路线。 ... [详细]
  • 如何在跨函数中使用内存?
    本文介绍了在跨函数中使用内存的方法,包括使用指针变量、动态分配内存和静态分配内存的区别。通过示例代码说明了如何正确地在不同函数中使用内存,并提醒程序员在使用动态分配内存时要手动释放内存,以防止内存泄漏。 ... [详细]
  • 本文介绍了Codeforces Round #321 (Div. 2)比赛中的问题Kefa and Dishes,通过状压和spfa算法解决了这个问题。给定一个有向图,求在不超过m步的情况下,能获得的最大权值和。点不能重复走。文章详细介绍了问题的题意、解题思路和代码实现。 ... [详细]
author-avatar
小王儿
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有