PTA 词频统计 (字符流预处理+STL容器+结构体排序)建议收藏加关注

该程序接收一段英文文本,统计不同单词数量,并输出词频最高的前10%的单词。处理时,将所有字符转为小写,去除非单词字符,并对超过15字符的单词截取前15个字符。输出包括不同单词总数和按词频降序排列的高频词。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

请编写程序,对一段英文文本,统计其中所有不同单词的个数,以及词频最大的前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

思路:在读入文本的时候直接把所有的字符转成小写,然后把符号变成空格,这样就可以在stringstream中直接按照空格切割,这样不管是 This  还是  “this” 还是   ,this'    最后都会变成 this 非常巧妙的思路。 

坑点分析:

1.超过15字符的单词要截掉多余部分,直接丢弃不用管。

2.处理过程中碰到 # 要!直!接!退!出!!!。

3.输出的时候先输出一行不同的词个数,善于利用PTA在线调试找不同。

4.计算10%的词语是算不同的词语个数,重复的只算一次。

5.输入要用getline(cin,s)一行一行读取。

超详细讲解AC代码附上: 

#include<bits/stdc++.h>
using namespace std;
struct node{//用来存关键词和出现次数 
	string name;
	int num;
}lst[100086];
bool cmp(node a,node b){//输出排序规则 
	if(a.num!=b.num )return a.num >b.num;
	return a.name <b.name ;
}
int cheak(char c){//检查是不是符号 
	if(c>='a'&&c<='z')return 1;
	if(c>='A'&&c<='Z')return 1;
	if(c>='0'&&c<='9')return 1;
	if(c=='_' ||c=='#')return 1;
	return 0;
}
int main(){
	string s;
	map<string,int>mp;
	int flag = true;//用来标记是否结束输入 
	while(getline(cin,s) &&flag){
		for(int i=0;i<s.length();i++){
			if(cheak(s[i])==0){
				s[i]=' ';//把符号换成空格 特判 # _ 不处理  
			}
			if(s[i]>='A'&&s[i]<='Z'){
				s[i] = s[i]-'A'+'a';//转小写 
			}
		}
		string s1;
		stringstream ss(s);//用字符串流分割空格,处理单词 
		while(ss>>s1){
			if(s1=="#"){//碰到#就结束输入 
				flag = false;
				break;
			}
			int len = s1.length();
			if(len>15){//单词大于15个就截取 
				s1 = s1.substr(0,15);
			}
			len = s1.length();
			mp[s1]++;//用map标记,去重+快速 
		}


		
	}
	cout<<mp.size()<<endl;//输出有多少个不同的关键词 
	int cnt=0;
	for(auto it:mp){ 
		//把map里的数据倒到结构体里面排序输出, 
		lst[cnt].name = it.first;
		lst[cnt].num = it.second;
		cnt++;
		
	}
	sort(lst,lst+cnt,cmp);
	//排序 
	int sl = cnt*0.1;//要输出的数量 10% = 0.1 
	for(int i=0;i<sl;i++){
		cout<<lst[i].num<<":"<<lst[i].name<<endl;
	}
	return 0;//别忘记return 0; (说的就是你小林)   
} 

求个关注

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值