一:题目
实现一种简单原始的文件相似度计算,即以两文件的公共词汇占总词汇的比例来定义相似度。为简化问题,这里不考虑中文(因为分词太难了),只考虑长度不小于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容器不了解的兄弟们来看一下)
四:上码(来兄弟们 干了这杯码 我们来日方长)
#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!我们共同进步!