江西财经大学第二届程序设计竞赛同步赛----E-是不是复读机

首先发出题目链接:
链接:https://ac.nowcoder.com/acm/contest/635/E
来源:牛客网

题目如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
看完题目之后就有两个问题摆在面前:
(1)题目输入的是一串英文,怎么把一串英语拆分成一个个单词;
(2)用什么来存储每个单词的频率(用数组?数组下标只能是正整数诶。。)

只要解决了这两个问题,题目不就做出来了吗。。

下面就来解决这两个问题!


第一个问题,把一串英文拆分成一个个单词:

由于英文中有空格,所以我们可以用string类型配合getline来存贮字符串(不要问我为什么不用char)

string str;
getline(cin,str);

然后来介绍一种拆分英语的方法:stringstream

至于stringstream的用法可以找其他博客

下面是拆分单词的代码:

stream<<s1;
while(stream>>str){
	···
}

这串代码可以形象的解释为:
把s1字符串全部放入一个流里面,然后通过while循环每次输出一个单词(由于此输出流遇到空格会停止输出)(在此只介绍一下,至于stringstream的功能可以自己去挖掘)

举个stringstream例子:

#include <bits/stdc++.h>
using namespace std;
stringstream str;
int main(){
	string b,a="hello world hello you";
	str<<a;
	while(str>>b){
		cout<<":";
		cout<<b<<endl;
	}
} 

输出:
:hello
:world
:hello
:you

看了这个例子有没有体会。
ps:当你使用同一stringstream类型的str进行多次转换时,一定要记得加上

str.clear();

比如:

#include <bits/stdc++.h>
using namespace std;
stringstream str;
map<string,string> map1;
int main(){
	string b,c;
	string d="what is that";
	string a="hello world hello you";
	str<<a;
	while(str>>b){
		cout<<":";
		cout<<b<<endl;
	}
	
	str.clear();
	
	str<<d;
	while(str>>c){
		cout<<":";
		cout<<c<<endl;
	}
} 

输出:
:hello
:world
:hello
:you
:what
:is
:that

你可以试一试把中间那个str.clear()去掉看看会发生什么。

忘记说了,字符串忽略大小写,可以先将原来的一句英语全部变成大写或者小写,然后再来分割单词,用transform或者遍历都可以


第二个问题,用什么来存储每个单词的频率:

废话不多说,可以用比较高级的“数组”------STL库的map

为啥说map是高级的数组

要知道数组的下标只能为非负整数

而map可以实现
a[“hello”]=1,b[‘A’]=2,c[-3.6]=3;

因为数组的键值只能为非负整数(a[1],a[2]),而map的键值可以为任何类型
map插入的方法可以像数组赋值一样(每赋一个值,map容器的size就加1,map容器实值初始值为0)

map的定义和pair差不多,比如:

map<double,int> map1;
pair<double,int> pair1;

在map的定义中,尖括号内第一个数据类型为map的键值(类比数组下标);
第二个数据类型才是map的实值(类比数组的存储类型)。

可以用auto来循环遍历map1内的元素

for(auto i:map1)

在这种情况下
i.first 访问map内元素i的下标;i.second访问map内元素i的的值。

map<string,int> a;
//string类型的键值,int类型的实值
cout<<a.size(); //=0;
cout<<a["nihao"]  //=0;
cout<<a.size();  //=1;
a["nihao"]=5;
cout<<a.size();  //=1;
cout<<a["nihao"].first<<endl;  //=nihao;
cout<<a["nihao"].second<<endl;  //=5

我们可以用键值当做单词类型,实值代表此单词的频率,配合pair(first为第一串英文单词频率,second为第二串单词频率),初始值都为0,可以放心使用自加;


最后得到了两段英文各个单词的频率,按照题目公式套用求解即可(用double类型


代码如下:

#include <string>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <map>
#include <cmath>
using namespace std;
typedef pair<int,int> P;
stringstream stream;
map<string,P> map1;
string s1,str;//s1存一条英文语句,str存单词
double x1=0,x2=0,x3=0;
void analyse(int d){//这个函数用来统计单词频率,参数d用来判断这是第几条英文语句(一共两条)
	getline(cin,s1);//输入一行
	transform(str.begin(),str.end(),str.begin(),::tolower);//transform函数在此用来统一此英文语句内单词为小写
	stream<<s1;//输入到stream内
	while(stream>>str)//每次向str输送一个单词
		d==1?map1[str].first++:map1[str].second++;//统计个数,map[str]对应str所存单词的频率
	stream.clear();//一定要记得清空stream
	return;
}

int main(){
	analyse(1);//输入并统计第一句英文单词数目
	analyse(2);//输入并统计第二句英文单词数目
	//以下都是计算cos值
	for(auto c:map1){
		x1+=c.second.first*c.second.second;
		x2+=pow(c.second.first,2);x3+=pow(c.second.second,2);
	}
	if(x1/sqrt(x2*x3)>=0.9)	cout<<"Yes"<<endl;
	else	cout<<"No"<<endl;
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值