【csp202403-2】相似度計算【第33次CCF計算機軟體能力認證】

SAKURA12發表於2024-05-26

題目背景

兩個集合的 Jaccard 相似度定義為:

即交集的大小除以並集的大小。當集合𝐴𝐵完全相同時,𝑆𝑖𝑚(𝐴,𝐵)=1取得最大值;當二者交集為空時,𝑆𝑖𝑚(𝐴,𝐵)=0取得最小值。

問題描述

除了進行簡單的詞頻統計,小P還希望使用Jaccard相似度來評估兩篇文章的相似性。具體來說,每篇文章均由若干個英文單片語成,且英文單詞僅包含“大小寫英文字母”。 對於給定的兩篇文章,小P首先需要提取出兩者的單詞集合𝐴𝐵,即去掉各自重複的單詞。 然後計算出:

  • ∣𝐴∩𝐵∣,即有多少個不同的單詞同時出現在兩篇文章中;
  • ∣𝐴∪𝐵∣,即兩篇文章一共包含了多少個不同的單詞。

最後再將兩者相除即可算出相似度。需要注意,在整個計算過程中應當忽略英文字母大小寫的區別,比如theTheTHE三者都應被視作同一個單詞。

試編寫程式幫助小 P 完成前兩步,計算出∣𝐴∩𝐵∣∣𝐴∪𝐵∣;小P將親自完成最後一步的除法運算。

輸入格式

從標準輸入讀入資料。

輸入共三行。

輸入的第一行包含兩個正整數𝑛𝑚,分別表示兩篇文章的單詞個數。

第二行包含空格分隔的𝑛個單詞,表示第一篇文章;

第三行包含空格分隔的𝑚個單詞,表示第二篇文章。

輸出格式

輸出到標準輸出。

輸出共兩行。

第一行輸出一個整數∣𝐴∩𝐵∣,即有多少個不同的單詞同時出現在兩篇文章中;

第二行輸出一個整數∣𝐴∪𝐵∣,即兩篇文章一共包含了多少個不同的單詞。

樣例1輸入

3 2
The tHe thE
the THE

樣例1輸出

1
1

樣例1解釋

A=B=AB=AB={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 }

相關文章