请编写程序,对一段英文文本,统计其中所有不同单词的个数,以及词频最大的前10%的单词。
所谓“单词”,是指由不超过80个单词字符组成的连续字符串,但长度超过15的单词将只截取保留前15个单词字符。而合法的“单词字符”为大小写字母、数字和下划线,其它字符均认为是单词分隔符。
输入格式:
输入给出一段非空文本,最后以符号#结尾。输入保证存在至少10个不同的单词。
输出格式:
在第一行中输出文本中所有不同单词的个数。注意“单词”不区分英文大小写,例如“PAT”和“pat”被认为是同一个单词。
随后按照词频递减的顺序,按照词频:单词的格式输出词频最大的前10%的单词。若有并列,则按递增字典序输出。
输入样例:
This is a test.
The word “this” is the word with the highest frequency.
Longlonglonglongword should be cut off, so is considered as the same as longlonglonglonee. But this_8 is different than this, and this, and this…#
this line should be ignored.
输出样例:(注意:虽然单词the也出现了4次,但因为我们只要输出前10%(即23个单词中的前2个)单词,而按照字母序,the排第3位,所以不输出。)
23
5:this
4:is
#include<algorithm>
using namespace std;
#include<stdio.h>
#include<string.h>
typedef struct NODE no;
struct NODE{
char corword[16];
int co;
}node[3000000];
int cmp(no a,no b)
{
if(a.co>b.co) return 1;
else if(a.co<b.co) return 0;
else
{
int flag=strcmp(a.corword,b.corword);
if(flag>0) return 0;
return 1;
}
}
char transf(char am)//转换大小写
{
if(am>='A'&&am<='Z') am=am+32;
return am;
}
int main(void)
{
for(int i=0; i<=3000000-1; i++)
{
node[i].co=0;
node[i].corword[0]=48;
}
int count=0;不同单词个数
char word;
int flag=0;出现#结束程序的标志
char tep[100];临时保存单词
int i=0;
while(word=getchar())开始用的scanf,但不会如何区分符号和单词了,所以用getchar
{
word=transf(word);
if(word=='#')
{
flag=1;
}
if(word>=48&&word<=57||word>=65&&word<=90||word>=97&&word<=122||word==95)
{
tep[i++]=word;
continue;
}
if(i>0)
{
int flag2=0;
if(i>15) tep[15]=NULL;
else tep[i]=NULL;
for(int j=0; j<=count-1; j++)
{
if(strcmp(tep,node[j].corword)==0)
{
node[j].co++;
flag2=1;
break;
}
}
if(flag2==0)
{
strcpy(node[count++].corword,tep);
}
i=0;
memset(tep,NULL,sizeof(tep));
}
else if(i==0&&flag==0) continue;
if(flag) break;
}
int pos=count*0.1;
sort(node,node+count,cmp);
printf("%d\n",count);
for(int j=0;j<pos;j++)
{
printf("%d:%s\n",node[j].co+1,node[j].corword);
}
return 0;
}
不用sort模板,用冒泡排序啥的也能过,懒得写了。(优化的话可以弄个数组指针。数组里面保存指针)