題目背景
兩個集合的 Jaccard 相似度定義為:
即交集的大小除以並集的大小。當集合𝐴和𝐵完全相同時,𝑆𝑖𝑚(𝐴,𝐵)=1取得最大值;當二者交集為空時,𝑆𝑖𝑚(𝐴,𝐵)=0取得最小值。
問題描述
除了進行簡單的詞頻統計,小P還希望使用Jaccard相似度來評估兩篇文章的相似性。具體來說,每篇文章均由若干個英文單片語成,且英文單詞僅包含“大小寫英文字母”。 對於給定的兩篇文章,小P首先需要提取出兩者的單詞集合𝐴和𝐵,即去掉各自重複的單詞。 然後計算出:
- ∣𝐴∩𝐵∣,即有多少個不同的單詞同時出現在兩篇文章中;
- ∣𝐴∪𝐵∣,即兩篇文章一共包含了多少個不同的單詞。
最後再將兩者相除即可算出相似度。需要注意,在整個計算過程中應當忽略英文字母大小寫的區別,比如the
、The
和THE
三者都應被視作同一個單詞。
試編寫程式幫助小 P 完成前兩步,計算出∣𝐴∩𝐵∣和∣𝐴∪𝐵∣;小P將親自完成最後一步的除法運算。
輸入格式
從標準輸入讀入資料。
輸入共三行。
輸入的第一行包含兩個正整數𝑛和𝑚,分別表示兩篇文章的單詞個數。
第二行包含空格分隔的𝑛個單詞,表示第一篇文章;
第三行包含空格分隔的𝑚個單詞,表示第二篇文章。
輸出格式
輸出到標準輸出。
輸出共兩行。
第一行輸出一個整數∣𝐴∩𝐵∣,即有多少個不同的單詞同時出現在兩篇文章中;
第二行輸出一個整數∣𝐴∪𝐵∣,即兩篇文章一共包含了多少個不同的單詞。
樣例1輸入
3 2
The tHe thE
the THE
樣例1輸出
1
1
樣例1解釋
A=B=A∩B=A∪B={the}
樣例2輸入
9 7
Par les soirs bleus dete jirai dans les sentiers
PICOTE PAR LES BLES FOULER LHERBE MENUE
樣例2輸出
2
13
樣例2解釋
A={bleus, dans, dete, jirai, les, par, sentiers, soirs}
∣𝐴∣=8
𝐵={bles, fouler, les, lherbe, menue, par, picote}
∣𝐵∣=7
𝐴∩𝐵={les, par}
∣𝐴∩𝐵∣=2
樣例3輸入
15 15
Thou that art now the worlds fresh ornament And only herald to the gaudy spring
Shall I compare thee to a summers day Thou art more lovely and more temperate
樣例3輸出
4
24
資料範圍
80%的測試資料滿足:𝑛,𝑚≤100且所有字母均為小寫;
全部的測試資料滿足:𝑛,𝑚≤104且每個單詞最多包含10個字母。
題解
本題要求兩篇文章單詞的交集和並集,我們只需要知道兩篇文章中一共出現了多少不同的單詞,以及同時在兩篇文章中出現過的單詞數,我們不需要知道一個單詞在哪篇文章中出現過。
對於每一個單詞開一個計數器,統計它在幾篇文章中出現過,由於一個單詞可能在一篇文章中出現多次,我們需要對單詞進行標記,只有在一篇文章中第一次出現的時候才令計數器加一。
最後,不同單詞的總個數就是並集的大小,計數為2的單詞個數就是交集的大小。
由於給的單詞大小寫不一致,可以先預處理把字母統一換成小寫字母或者大寫字母。
1 #include <iostream> 2 #include <cstdio> 3 #include <string> 4 #include <map> 5 using namespace std; 6 int n,m,s1,s2; 7 string ch; 8 map<string,int> mp; 9 map<string,bool> vis; 10 int main() 11 { 12 int i,j,len; 13 scanf("%d%d",&n,&m); 14 for (i=1;i<=n;i++) 15 { 16 cin>>ch; 17 len=ch.length(); 18 for (j=0;j<len;j++) 19 if (ch[j]>='A' && ch[j]<='Z') 20 ch[j]=ch[j]-'A'+'a'; 21 if (!vis[ch]) mp[ch]++; 22 vis[ch]=1; 23 } 24 for (auto &t:vis) 25 { 26 t.second=0; 27 } 28 for (i=1;i<=m;i++) 29 { 30 cin>>ch; 31 len=ch.length(); 32 for (j=0;j<len;j++) 33 if (ch[j]>='A' && ch[j]<='Z') 34 ch[j]=ch[j]-'A'+'a'; 35 if (!vis[ch]) mp[ch]++; 36 vis[ch]=1; 37 } 38 for (auto &t:mp) 39 { 40 if (t.second==2) s1++; 41 if (t.second>0) s2++; 42 } 43 printf("%d\n%d\n",s1,s2); 44 return 0; 45 }