列表

详情


NC24553. 是不是复读机

描述

在复读纪元2140年,复读机(们)已经放弃了如下所示的低级复读方式:

“哟,小伙汁,想不到你也是个复读机”

“哟,小伙汁,想不到你也是个复读机”

而是进化出了一种新的复读技巧:语义复读,即能复读出字面上高度相似的句子(单词顺序不一定一样)。譬如,在发生以下对话时,我们可以认为,参与对话的两人中存在复读机:

I am not a repeater

I am not a repeater too

   现在我就来教你如何辨认复读机.
1.  提取出所有的单词,并统计每一句中的词频。
2.  通过余弦相似度算法进行相似度分析。

我们知道,在二维向量中,假设a向量是(x1, y1),b向量是(x2, y2),那么可以将余弦定理改写成下面的形式:

将我们之前提取出的词频看成2n维向量,可得到(1,1,1,1,1,0)和(1,1,1,1,1,1)两个向量,进行余弦计算,可得到

我们认为其相似度为0.912,当相似度不小于90%时,我们就认为对话的两人中,存在复读机。

输入描述

输入包括两行由数字(0-9)、英文字符(a-z、A-Z)和空格组成的字符串。其中单词之间通过空格分隔且不区分大小写,即我们认为“At”、“at”、“AT”、“aT”为同一个单词。每个字符串总长度不超过2000.

输出描述

在一行中输出结果,如果存在复读机,则输出“Yes”,否则输出“No”,不包含双引号。

示例1

输入:

I am not a reapter
I am not a reapter too

输出:

Yes

示例2

输入:

Excuse me Can you tell me how much the shirt is
Yes it is nine fifteen

输出:

No

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 5ms, 内存消耗: 1380K, 提交时间: 2019-04-13 14:07:11

#include <bits/stdc++.h>
using namespace std;
char ch;
char s1[2005][2005], s2[2005][2005];
int num = 0;
map<string, int>mp;
int main()
{
	int cnt1 = 0, cnt2 = 0;
	for (int i = 0; true; i++)
	{
		scanf("%s%c", s1[i], &ch);
		for (int j = 0; j < strlen(s1[i]); j++)
			s1[i][j] = tolower(s1[i][j]);
		mp[s1[i]] = 1;
		cnt1++;
		if (ch == '\n')
			break;
	}
	for (int i = 0; true; i++)
	{
		scanf("%s%c", s2[i], &ch);
		for (int j = 0; j < strlen(s2[i]); j++)
			s2[i][j] = tolower(s2[i][j]);
		if (mp[s2[i]] != 0)
			num++;
		cnt2++;
		if (ch == '\n')
			break;
	}
	double ans = 0;
	ans = num * 1.0 / sqrt(cnt1 * 1.0) / sqrt(1.0 * cnt2);
	if (ans >= 0.90)
		printf("Yes");
	else
		printf("No");
}

C++11(clang++ 3.9) 解法, 执行用时: 5ms, 内存消耗: 600K, 提交时间: 2019-04-18 12:44:06

#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;
double x1=0,x2=0,x3=0;
void analyse(int d){
	getline(cin,s1);
	transform(s1.begin(),s1.end(),s1.begin(),::tolower);
	stream<<s1;
	while(stream>>str)	d==1?map1[str].first++:map1[str].second++;
	stream.clear();
	return;
}
int main(){
	analyse(1);
	analyse(2);	
	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;
}

上一题