江西财经大学第二届程序设计竞赛——E
************是不是复读机?**************
题目描述:
链接:https://ac.nowcoder.com/acm/contest/635/E
来源:牛客网
在复读纪元2140年,复读机(们)已经放弃了如下所示的低级复读方式:
“哟,小伙汁,想不到你也是个复读机”
“哟,小伙汁,想不到你也是个复读机”
而是进化出了一种新的复读技巧:语义复读,即能复读出字面上高度相似的句子(单词顺序不一定一样)。譬如,在发生以下对话时,我们可以认为,参与对话的两人中存在复读机:
“I am not a repeater”
“I am not a repeater too”
现在我就来教你如何辨认复读机.
1. 提取出所有的单词,并统计每一句中的词频。
2. 通过余弦相似度算法进行相似度分析。
我们知道,在二维向量中,假设a向量是(x1, y1),b向量是(x2, y2),那么可以将余弦定理改写成下面的形式:
将我们之前提取出的词频看成2个n维向量,可得到(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”,不包含双引号。
样列输入&&输出
输入
I am not a reapter
I am not a reapter too
输出
Yes
输入
Excuse me Can you tell me how much the shirt is
Yes it is nine fifteen
此题中我们需要统计两个字符串中出现过的单词在两个字符串中个对应的个数,如果一个单词在一个字符串中出现了而在另一个中没有
则认为是0
因此我们需要一个东西来储存出现过的单词(用vector容器)
还需要另一个东西来储存这个单词在字串中出现过的次数(map<string,int>)
我们需要把字符串中的单词分割开,这时候就要出现stringstrream的作用,这个函数可以将字符串按空格分开,然后分给另一个字符串
通过这样我们就可以解决此题
首先是string字符串的读入,并且把小写都变成大写
string s1,s2; getline(cin,s1); getline(cin,s2); //getline(cin,s2); for(int i=0;i<s1.length();i++) { if(s1[i]>='A'&&s1[i]<='Z') s1[i]+=32; } for(int i=0;i<s2.length();i++) { if(s2[i]>='A'&&s2[i]<='Z') s2[i]+=32; }
然后是统计单词的个数
stringstream sss(s1); string tmp; while(sss>>tmp) { if(!cnt1[tmp]&&!cnt2[tmp]) vec.push_back(tmp); cnt1[tmp]++; } stringstream ss(s2); while(ss>>tmp) { if(!cnt1[tmp]&&!cnt2[tmp]) vec.push_back(tmp); cnt2[tmp]++; }
然后就是普通的计算问题了
我是参考学长的代码写的(碾都红了)
#include<bits/stdc++.h> using namespace std; map< string,int>cnt1,cnt2; vector<string> vec; int main() { string s1,s2; getline(cin,s1); getline(cin,s2); //getline(cin,s2); for(int i=0;i<s1.length();i++) { if(s1[i]>='A'&&s1[i]<='Z') s1[i]+=32; } for(int i=0;i<s2.length();i++) { if(s2[i]>='A'&&s2[i]<='Z') s2[i]+=32; } stringstream sss(s1); string tmp; while(sss>>tmp) { if(!cnt1[tmp]&&!cnt2[tmp]) vec.push_back(tmp); cnt1[tmp]++; } stringstream ss(s2); while(ss>>tmp) { if(!cnt1[tmp]&&!cnt2[tmp]) vec.push_back(tmp); cnt2[tmp]++; } double x=0,y=0,z=0; for(int i=0;i<vec.size();i++) { x+=cnt1[vec[i]]*cnt2[vec[i]]; y+=cnt1[vec[i]]*cnt1[vec[i]]; z+=cnt2[vec[i]]*cnt2[vec[i]]; } z=sqrt(z),y=sqrt(y); double ans=x/z/y; if(ans>=0.9) cout<<"Yes"<<endl; else cout<<"No"<<endl; return 0; }