实现一种简单原始的文件相似度计算,即以两文件的公共词汇占总词汇的比例来定义相似度。为简化问题,这里不考虑中文(因为分词太难了),只考虑长度不小于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%
这道题还是相对来说在今天做的题里蛮简单的,只要留意ddd@aaa这种情况是两个词,可以用stringstream处理这种情况,其他的地方都跟天体二阶题<集合相似度>差不多
//
// Created by TIGA_HUANG on 2020/10/6.
//
#include <iostream>
#include <vector>
#include <set>
#include <iomanip>
#include <sstream>
using namespace std;
int N;
set<string> v[105];
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin >> N;
string str;
for (int i = 0; i < N; ++i) {
do {
cin >> str;
if (str == "#")
continue;
for (int j = 0; str[j]; ++j) {
if (isupper(str[j]))
str[j] = str[j] - 'A' + 'a';
if (!(isupper(str[j]) || islower(str[j]))) {
str[j] = ' ';
}
}
stringstream ss;
ss << str;
while(ss >> str) {
if (str.length() > 10) {
str = str.erase(10);
v[i + 1].insert(str);
} else if (str.length() > 2) {
v[i + 1].insert(str);
}
}
} while (str != "#");
}
int K;
cin >> K;
set<string> sc;
for (int i = 0; i < K; ++i) {
int a, b, same = 0;
cin >> a >> b;
for (const auto & item : v[a]) {
if (v[b].count(item)) {
same++;
}
}
cout << fixed << setprecision(1) << same * 100.0 / (v[a].size() + v[b].size() - same) << "%\n";
sc.clear();
}
return 0;
}