实现一种简单原始的文件相似度计算,即以两文件的公共词汇占总词汇的比例来定义相似度。为简化问题,这里不考虑中文(因为分词太难了),只考虑长度不小于3、且不超过10的英文单词,长度超过10的只考虑前10个字母。
输入格式:
输入首先给出正整数N(≤100),为文件总数。随后按以下格式给出每个文件的内容:首先给出文件正文,最后在一行中只给出一个字符#
,表示文件结束。在N个文件内容结束之后,给出查询总数M(≤104),随后M行,每行给出一对文件编号,其间以空格分隔。这里假设文件按给出的顺序从1到N编号。
输出格式:
针对每一条查询,在一行中输出两文件的相似度,即两文件的公共词汇量占两文件总词汇量的百分比,精确到小数点后1位。注意这里的一个“单词”只包括仅由英文字母组成的、长度不小于3、且不超过10的英文单词,长度超过10的只考虑前10个字母。单词间以任何非英文字母隔开。另外,大小写不同的同一单词被认为是相同的单词,例如“You”和“you”是同一个单词。
输入样例:
3
Aaa Bbb Ccc
#
Bbb Ccc Ddd
#
Aaa2 ccc Eee
is at Ddd@Fff
#
2
1 2
1 3
输出样例:
50.0%
33.3%
解题思路:
- 构建set数组,用于存储每个文件的词汇。
- 每次读取一行字符串,并通过deal()函数对字符串进行处理,每个字符串末尾加上'.',以便最后一个单词的读取。
- deal遍历读取字符串每一个元素,如果遇到字母字符,将其添加至word中;如果遇到非字符元素,判断word中字符数量,若满足条件,将其加入对应的set容器中。
- 根据编号遍历两个容器,统计两个容器中相同的元素个数,输出相似度。
代码如下:
#include <iostream>
#include <set>
#include <string>
using namespace std;
#define Max 100
void deal(string a,int num);
set<string> file[Max];
int main(){
int i,n;
cin>>n;
getchar();
for(i=0;i<n;i++){
string word;
getline(cin,word);
while(word!="#"){
deal(word,i);
getline(cin,word);
}
}
int a1,a2;
cin>>n;
for(i=0;i<n;i++){
cin>>a1>>a2;
a1--;a2--;
int cnt=0;
int total=file[a1].size()+file[a2].size();
set<string>::iterator it;
for(it=file[a1].begin();it!=file[a1].end();it++){
if(file[a2].find(*it)!=file[a2].end())
cnt++;
}
printf("%0.1f%\n",100.0*cnt/(total-cnt));
}
return 0;
}
void deal(string a,int num){
string word;
a+='.';
int i;
for(i=0;i<a.size();i++){
if(isalpha(a[i])){
if(word.size()<10)
word+=tolower(a[i]);
}
else {
if(word.size()>2){
file[num].insert(word);
}
word.clear();
}
}
}