题目背景
两个集合的 Jaccard 相似度定义为:𝑆𝑖𝑚(𝐴,𝐵)=∣𝐴∩𝐵∣∣𝐴∪𝐵∣Sim(A,B)=∣A∪B∣∣A∩B∣即交集的大小除以并集的大小。当集合 𝐴A 和 𝐵B 完全相同时,𝑆𝑖𝑚(𝐴,𝐵)=1Sim(A,B)=1 取得最大值;当二者交集为空时,𝑆𝑖𝑚(𝐴,𝐵)=0Sim(A,B)=0 取得最小值。
题目描述
除了进行简单的词频统计,小 P 还希望使用 Jaccard 相似度来评估两篇文章的相似性。 具体来说,每篇文章均由若干个英文单词组成,且英文单词仅包含“大小写英文字母”。 对于给定的两篇文章,小 P 首先需要提取出两者的单词集合 𝐴A 和 𝐵B,即去掉各自重复的单词。 然后计算出:
- ∣𝐴∩𝐵∣∣A∩B∣,即有多少个不同的单词同时出现在两篇文章中;
- ∣𝐴∪𝐵∣∣A∪B∣,即两篇文章一共包含了多少个不同的单词。
最后再将两者相除即可算出相似度。 需要注意,在整个计算过程中应当忽略英文字母大小写的区别,比如 the
、The
和 THE
三者都应被视作同一个单词。
试编写程序帮助小 P 完成前两步,计算出 ∣𝐴∩𝐵∣∣A∩B∣ 和 ∣𝐴∪𝐵∣∣A∪B∣;小 P 将亲自完成最后一步的除法运算。
输入格式
从标准输入读入数据。
输入共三行。
输入的第一行包含两个正整数 𝑛n 和 𝑚m,分别表示两篇文章的单词个数。
第二行包含空格分隔的 𝑛n 个单词,表示第一篇文章;
第三行包含空格分隔的 𝑚m 个单词,表示第二篇文章。
输出格式
输出到标准输出。
输出共两行。
第一行输出一个整数 ∣𝐴∩𝐵∣∣A∩B∣,即有多少个不同的单词同时出现在两篇文章中;
第二行输出一个整数 ∣𝐴∪𝐵∣∣A∪B∣,即两篇文章一共包含了多少个不同的单词。
题解:
解题思路,将每个单词全部转化为大写,然后用哈希表统计出现的单词。统计第一篇文章的时候可以把没有出现的词汇数量可以全部累加到并集中,统计第二篇文章时,先统计出现的词汇是否能在第一篇文章中找到,如果能找到那么就统计到并集中去,否则再第二个哈希表中查找,如果没能找到那么就可以将其统计的并集中。
#include<bits/stdc++.h>
#define int long long
#define up(l,r,i) for(int i=l,END##i=r;i<=END##i;++i)
#define dn(r,l,i) for(int i=r,END##i=l;i>=END##i;--i)
using namespace std;
#define IOS ios::sync_with_stdio("false");cin.tie(0);cout.tie(0);
#define freopen freopen("IN.in","r",stdin);freopen("OUT.out","w",stdout);
typedef pair<int,int> PII;
const int N=1e5+10;
const int INF=0x7ffffff;
unordered_map<string,bool> m1,m2;
string str;
int m,n,com=0,con=0;
signed main(){
IOS
cin>>m>>n;
while(m--){
string str;
cin>>str;
transform(str.begin(),str.end(),str.begin(),::toupper);
auto it=m1.find(str);
if(it==m1.end()){
com++;
m1[str]=true;
}
}
while(n--){
string str;
cin>>str;
transform(str.begin(),str.end(),str.begin(),::toupper);
auto it=m1.find(str);
if(it!=m1.end()){
if(m1[str]){
con++;
m1[str]=false;
}
}else{
if(auto it1=m2.find(str);it1==m2.end()){
com++;
m2[str]=true;
}
}
}
cout<<con<<endl<<com;
return 0;
}