词频统计
【问题描述】
编写程序统计一个英文文本文件中每个单词的出现次数(词频统计),并将统计结果按单词出现频率由高至低输出到指定文件中。
本题采用的数据结构为trie树,也称为字典树,具体请参考相关资料。
注:在此单词为仅由字母组成的字符序列。包含大写字母的单词应将大写字母转换为小写字母后统计。此外,由于输入文件是英文小说,因此不会出现无意义的单词。
【输入形式】
打开当前目录下文件in.txt,从中读取英文单词进行词频统计。
【输出形式】
按单词出现次数由高至低输出前100个(不足100个按实际个数输出),每行输出一个单词及其出现次数,单词和其出现次数间由一个空格分隔。
【分析】
此题为经典的字典树,此处不提供字典树的介绍和讲解,故只提供代码,如果看不懂的话可以先去学习一下字典树。
【代码】
#include<iostream>
#include<fstream>
#include<string.h>
#include<algorithm>
#include<stack>
using namespace std;
int tree[100005][27];//用于表示字典树的所有可能结点
int cnt[100005]; //用于记录每个节点作为最后一个结点出现的次数,也即每个单词出现的次数
int num=0; //用于表示当前已使用的最后一个结点的编号
string str; //用于递归求取字典树上记录的所有单词
char s[100005]; //用于记录当个单词
char text[1000000005];//记录提供的文本
void insert(char *str)//向字典树中插入结点
{
int cur=0;
int index=0;
int size=strlen(str);
while(index!=size)
{
if(tree[cur][str[index]^96]==0)
{
tree[cur][str[index]^96]=++num;
}
cur=tree[cur][str[index++]^96];
}
cnt[cur]++;
return ;
}
struct _String{
string str;
int num;
_String(string& s,int n):str(s),num(n){}
_String(){}
_String(const _String& s){this->str=s.str; this->num=s.num;}
}S[100005];//记录出现的单词
bool cmp(_String& a,_String& b)//比较函数,用于对单词的出现次数进行排序
{
if(a.num==b.num)
return a.str<b.str;
return a.num>b.num;
}
int num_of_str=0;//统计出现的单词的数目
void GetString(int cur)//递归整棵字典树,求取其中记录的所有单词
{
if(cnt[cur]!=0)
{
S[num_of_str++]=_String(str,cnt[cur]);
}
for(int i=1;i<=26;i++)
{
if(tree[cur][i]!=0)
{
str.push_back(char(i|96));
GetString(tree[cur][i]);
str.pop_back();
}
}
return ;
}
void ReadStr()//读取文本,提取出其中的单词并插入到树中
{
ifstream fin;
fin.open("in.txt",ios::in);
if(fin.fail())
{
cout<<"Error";
return ;
}
fin.getline(text,1000000005,EOF);
fin.close();
char ch;
int len=0,index=0;
while(text[index]!='\0')
{
ch=text[index++];
if(ch<='z' && ch>='a')
{
s[len++]=ch;
}
else if(ch<='Z' && ch>='A')
{
s[len++]=ch-'A'+'a';
}
else if(len!=0)
{
s[len]='\0';
len=0;
insert(s);
}
}
}
void Writestr()//排序并输出
{
sort(S,S+num_of_str,cmp);
ios::sync_with_stdio(0);
cout.tie(0);
for(int i=0;i<min(100,num_of_str);i++)
{
cout<<S[i].str<<' '<<S[i].num<<'\n';
}
}
int main()
{
ReadStr();
GetString(0);
Writestr();
return 0;
}
6044





