PTA 热点新闻(STL容器+模拟)

我们可以利用搜索引擎搜索网页等资源,再借助一些工具就可以生成这样的“词云”:

嫑犯愁,现在不要求生成这样的词云,而是换个简单些的要求:

对于输入的若干篇新闻报道以及若干个搜索关键词统计输出包含各关键词的新闻篇数,并输出包含最热关键词的新闻概要

输入格式:

输入由前后两部分组成。

第一部分是不超过100000篇新闻报道,每篇新闻的格式是:

  • 第1行是新闻标题,长度大于零且不超过60
  • 第2行是新闻发布日期,由8位数字组成,格式是yyyymmdd(4位年+2位月+2位日)
  • 接下来若干行是新闻正文,总长度大于零且不超过500由若干标点空格换行组成,所有字符为英文半角字符。
  • 标点仅有 , . ? : !五种,且标点都是单独出现,绝对不会出现相邻两个字符都是标点的情况。
  • 是由不超过30个连续的字母、数字、符号等非空格、非换行符组成的,词不包含以上五种标点,但标点有可能紧跟在一个词的末尾。例如文本Look! There is a u-turn!中,有五个词Look There is a u-turn

两篇新闻之间,有一行分隔符------(连续6个-);全部新闻结束后,有一行分隔符######(连续6个#)。新闻标题和正文中保证不出现这两种分隔符。

分隔符######之后,是第二部分,由2行组成:

  • 第1行是不超过10000的正整数N和不超过100000的非负整数K,由空格分隔。
  • 第2行是N个不超过30位的各不相同的搜索关键词,这些关键词仅包含小写字母、数字,不含大写字母、符号。

输出格式:

输出由前后两部分组成。
首先对于每个搜索关键词,统计新闻正文中出现该词的新闻篇数,注意:(1)仅统计新闻正文,不统计新闻标题,(2)不区分大小写,例如Alienalien是相同的词,(3)区分词的时态、单复数、包含符号等各种变化形式,例如aliensalien是不同的词u-turnuturn是不同的词(4)显然,若一个词在所有新闻中均未出现,则篇数为0,(5)统计的是出现关键词的新闻篇数,不是词出现的次数。

题目保证至少有一个关键词在至少一篇新闻中出现。

对于每个搜索关键词,若该词出现篇数不低于K,则输出在第一部分:

  • 每行一词,格式为 词:篇数
  • 若不低于K篇的多于一词,则按照篇数从高到低输出;若有多于一词篇数相同,则这些词按照词的字典序(英文字母从a至b排序、数字从0至9排序,数字排在字母之前)输出
  • 若不存在不低于K篇的词,则输出一行None!

在第二部分,对于出现篇数最高、且关键词的字典序最前的词,按照新闻的输入顺序,依次输出包含这个关键词的新闻概要,每条新闻一行,格式是新闻标题/发布日期

输入样例:

5篇新闻,6个搜索关键词,如下所示:

ALIENS APPEARED IN NEW YORK
20200320
The New York Roadside News Agency reported that yesterday a citizen
found an alien on Fifth Avenue in New York.
   The alien snatched a Pear u-phone from the citizen.
------
The Russians caught an alien!
20210322
BBC News reported that a Russian captured an alien in the Siberian forest.
  It turned out that the Russian was drunk and what he caught was a polar bear.
------
Does anyone know this bear?
20190615
Reuters reported that a lost bear was found in Paddington, London.
  The animal rescue organization tried to find a home for the poor bear.
------
New discoveries in Egypt
20180909
Agence France-Presse reported that
Egypt discovered an unknown element in a pyramid built five thousand years ago.
  The pyramid is suspected to be an alien relic.
------
Are you ALIEN?
20210322
The Associated Press reported that a study by the Royal Academy of Sciences showed that
10% of the population of our planet are aliens. Too frightening!
    So, are you an alien? How to prove to others that you are not an alien?
######
6 1
bear citizen about alien home academy

输出样例:

输入的K1,因此按规定顺序输出包含篇数不低于1的关键词(alien出现在4篇新闻中,bear出现在2篇新闻中,about未出现在任何新闻中,其余3词出现在1篇新闻中),并按顺序输出包含alien的新闻概要,如下所示:

alien:4
bear:2
academy:1
citizen:1
home:1
ALIENS APPEARED IN NEW YORK/20200320
The Russians caught an alien!/20210322
New discoveries in Egypt/20180909
Are you ALIEN?/20210322

思路:结构体套map会超时,必须得按照关键词找文章,不能以文章找关键词,不然猛猛超

坑点:

1.查找关键词的时候只找正文,标题不管

2.不管输出第一部分输出的是不是none,第二部分都要输出出现次数最高的关键词,题目保证了一定会有关键词被匹配;

3.不能直接用find 不然 alines 和 aline 在 找“aline” 时会被统计2次, 但是根据题意,复数形式不能算。

4.文章的标题是会重复的,日期也是,存在极端样例一天内发10篇一样标题,时间,内容的文章,(标题+时间都是一致的),所以要根据输入的顺序为文章分配编号,不然过不了。

AC代码

#include<bits/stdc++.h>
using namespace std;
int n,m,k,t,cnt=0;
struct node{
	//存文章的属性信息 
    string title;
    string time;
}mp[100086];
map<string,map<int,int> >mpp;//以关键词建索引文章 
struct ans{
	//存答案 
    int num;
    vector<int>link;//存指向的文章 
    string key;
}lst[10086];
bool cmp(ans a,ans b){//输出排序 
    if(a.num!=b.num)return a.num > b.num;
    return a.key < b.key;
}
int main(){
    ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    int now_type=0;//用来标记当前输入的是什么; 
    string s;
    //0-标题输入 1-时间驶入 2-正文输入 3-结束 
    while(getline(cin,s)){
    	//如果是------ 表示一篇文章结束 
        if(s =="------"){
            cnt++;//文章编号++ 
            now_type=0;//初始化 
            continue;
        }else if(s=="######"){
            cnt++;//这里也要加 
            break;
        }
        switch(now_type){
            case 0://标题输入 
                mp[cnt].title = s;
                now_type = 1;
                break;
            case 1://时间输入 
                mp[cnt].time = s;
                now_type = 2;
                break;
            case 2://正文输入
				//对字符串进行预处理
				//先全部转小写 
                for(int k=0;k<s.length();k++){
                    if(s[k]>='A'&&s[k]<='Z'){
                        s[k] = s[k]-'A' + 'a';
                    }
                }
 				//利用stringstream字符串流切割空格
                stringstream  ss(s);
                string s1;
                while(ss >> s1){
                    int le = s1.length();
                    if(s1[le-1]=='?'||s1[le-1]=='!'||s1[le-1]==':'||s1[le-1]==','||s1[le-1]=='.'){
                    	//擦去符号存入 
                        s1 = s1.erase(s1.length()-1,1);
                    }
                    //mpp[关键词] -》 size就是文章篇数 
                    mpp[s1][cnt]=1;
                }
                break;
        }
    }
    
    cin>>n>>k;
    //输入关键词 
    for(int i=0;i<n;i++){
        cin>>s;
        lst[i].key = s;
        lst[i].num = mpp[s].size(); //mpp[关键词] -》 size就是文章篇数 
        for(auto it:mpp[s]){//遍历mpp[s]出来的就是包含S关键词的文章编号; 
            lst[i].link.push_back(it.first);
        }
    }
 
    sort(lst,lst+n,cmp);//对结果排序 
    
    int f =0;//用来标记是否有 >K 的输出 
    for(int i=0;i<n;i++){
        if(lst[i].num<k)continue;
        f=1;
        cout<<lst[i].key<<":"<<lst[i].num<<endl;
    }
    if(f==0){
        cout<<"None!"<<endl;
    }
    
    //不管上方是否有输出,都要输出关键词篇数最多的文章
	//题目数据保证一定有一个关键词能被匹配 
    for(auto it:lst[0].link){
    	
        cout<<mp[it].title<<"/"<<mp[it].time<<endl;
    }

    return 0;
}

2023/04/09 更新 优化版

#include<bits/stdc++.h>
using namespace std;
map<string,map<int,int> > mp;
map<int,string>title;
map<int,string>tim;
struct node{
	string key;
	int  num;
}lst[10086];
bool cmp(node a,node b){
	if(a.num!=b.num )return a.num > b.num;
	return a.key  <b.key;
}
int main(){
	string s;
	int now=0;
	int cnt =0;
	while(getline(cin,s)){
		if(s=="######"){
			cnt++;
			break;
		}
		if(now == 0){
			title[cnt]=s;
			now=1;
		}else if(now == 1){
			tim[cnt]=s;
			now=2;
		}else if(now == 2){
			if(s=="------"){
				cnt++;
				now = 0;
			}
			for(int i=0;i<s.length();i++){
				if(s[i]>='A'&&s[i]<='Z')s[i] = char(s[i]-'A'+'a');
				if(s[i]==',' || s[i]=='.' ||s[i]=='?' ||s[i]=='!' ||s[i]==':'){
					s[i]=' ';
				}
			}
			stringstream ss(s);
			string s1;
			while(ss>>s1){
				mp[s1][cnt]=1;
			}
		}
	}
	int n,m;
	cin>>n>>m;
	for(int i=0;i<n;i++){
		string key;
		cin>>key;
		lst[i].key = key;
		lst[i].num = mp[key].size();
	}
	sort(lst,lst+n,cmp);
	int f =0;
	for(int i=0;i<n;i++){
		if(lst[i].num >= m){
			cout<<lst[i].key<<":"<<lst[i].num<<endl;
			f =1;
		}else{
			break;
		}
	}
	if(f==0)cout<<"None!"<<endl;
	for(auto it:mp[lst[0].key]){
		cout<<title[it.first]<<"/"<<tim[it.first]<<endl;
	}
	return 0;
}

  • 13
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值