7-44 基于词频的文件相似度 (30 分)
实现一种简单原始的文件相似度计算,即以两文件的公共词汇占总词汇的比例来定义相似度。为简化问题,这里不考虑中文(因为分词太难了),只考虑长度不小于3、且不超过10的英文单词,长度超过10的只考虑前10个字母。
输入格式:
输入首先给出正整数$N$(≤100),为文件总数。随后按以下格式给出每个文件的内容:首先给出文件正文,最后在一行中只给出一个字符#,表示文件结束。在$N$个文件内容结束之后,给出查询总数$M$(≤104),随后$M$行,每行给出一对文件编号,其间以空格分隔。这里假设文件按给出的顺序从1到$N$编号。
输出格式:
针对每一条查询,在一行中输出两文件的相似度,即两文件的公共词汇量占两文件总词汇量的百分比,精确到小数点后1位。注意这里的一个“单词”只包括仅由英文字母组成的、长度不小于3、且不超过10的英文单词,长度超过10的只考虑前10个字母。单词间以任何非英文字母隔开。另外,大小写不同的同一单词被认为是相同的单词,例如“You”和“you”是同一个单词。
输入样例:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | 3Aaa Bbb Ccc
 #
 Bbb Ccc Ddd
 #
 Aaa2 ccc Eee
 is at Ddd@Fff
 #
 2
 1 2
 1 3
 
 | 
输出样例:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 
 | #include<iostream>#include<string>
 #include<set>
 
 using namespace std;
 
 set<string> sets[100];
 
 int main() {
 int N;
 scanf("%d", &N);
 getchar();
 for(int i = 0; i < N; i++) {
 string str = "";
 while(true) {
 char c = getchar();
 if(c == '#') {
 break;
 } else if((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
 if(c >= 'a' && c <= 'z') {
 c = c - 'a' + 'A';
 }
 str += c;
 } else {
 if(str.length() >= 3) {
 if(str.length() > 10){
 str = str.substr(0, 10);
 }
 sets[i].insert(str);
 }
 str = "";
 }
 }
 }
 int M;
 scanf("%d", &M);
 for(int i = 0; i < M; i++) {
 int num1, num2;
 scanf("%d %d", &num1, &num2);
 int common = 0;
 for(set<string>::iterator it = sets[num1 - 1].begin(); it != sets[num1 - 1].end(); it++){
 if(sets[num2 - 1].find(*it) != sets[num2 - 1].end()){
 common++;
 }
 }
 int total = sets[num1 - 1].size() + sets[num2 - 1].size() - common;
 printf("%.1f%\n", common * 100.0 / total);
 }
 return 0;
 }
 
 |