一:题目
实现一种简单原始的文件相似度计算,即以两文件的公共词汇占总词汇的比例来定义相似度。为简化问题,这里不考虑中文(因为分词太难了),只考虑长度不小于3、且不超过10的英文单词,长度超过10的只考虑前10个字母。
输入格式:
输入首先给出正整数N(≤100),为文件总数。随后按以下格式给出每个文件的内容:首先给出文件正文,最后在一行中只给出一个字符#,表示文件结束。在N个文件内容结束之后,给出查询总数M(≤10
4
),随后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容器,这个容器我也是第一次用,这个他有自动去重的特性,而且,这个容器相较于map容器他只有关键值 ,其他用法类似,但要在注意的是,这里的迭代器都是指针,即遍历容器返回值都是指针
三:知识速递(对set容器不了解的兄弟们来看一下)
set基本用法
四:上码(来兄弟们 干了这杯码 我们来日方长)
#include<bits/stdc++.h>
using namespace std;set<string>s[100]; void manage(string str,int x){string word = "";//初始化字符串 str+="!";//表示最后一个单词的结束 什么符号都可以 for( int i = 0; i < str.size(); i++ ){if( isalpha (str[i]) ){//判断单个字符是否为字母 if( word.size() < 10){//处理字母个数小于10个的单词 word+=tolower(str[i]);//将大写字母转换成小写字母 }}else{if( word.size() > 2 ){s[x].insert(word);}word.clear();//将字符串的内容清空 为下一次调用函数做准备 } }
}int main(){int N;cin >> N;getchar();//处理换行符 当cin 和 getline() 一块用的时候 for( int i = 0; i < N; i++ ){string str = "";//初始化字符串 while( str != "#" ){manage(str,i);getline(cin,str);//每次是读进来一行 }}
// set<string>::iterator t;
// for( t = s[0].begin(); t != s[0].end(); t++ ){
// cout << *t << ' ';
// }int M;cin >> M; for( int i = 0; i < M; i++ ){int a,b,count = 0;cin >> a >> b;a--; b--;int total_length = s[a].size() + s[b].size();set<string>::iterator t;for( t = s[a].begin(); t != s[a].end(); t++ ){if( s[b].find(*t) != s[b].end() )//判断相同元素的个数 count++;} // cout << total_length << endl;printf("%0.1lf%\n",100.0 * count/(total_length - count)); } }
五:总结
这道题思路不是我的,我是没思路,就学大佬的了,但也是收获满满,我又学到一种容器 set;我前面在学map容器时就遇到过,但我没去学,因为没用到过,等到用到了再去学,在我看来,知识是永远学不完的,我们必须先上路,遇到什么问题就解决什么问题。不断扩充我们的武器库,比如map,vector,再接下来set;我会的会越来越多 ,加油BOY!我们共同进步!