实现一种简单原始的文件相似度计算,即以两文件的公共词汇占总词汇的比例来定义相似度。为简化问题,这里不考虑中文(因为分词太难了),只考虑长度不小于3、且不超过10的英文单词,长度超过10的只考虑前10个字母。

输入格式:

输入首先给出正整数N(≤),为文件总数。随后按以下格式给出每个文件的内容:首先给出文件正文,最后在一行中只给出一个字符#,表示文件结束。在N个文件内容结束之后,给出查询总数M(≤),随后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%

用map统计,不过注意一点map在查询时会改变其size().
代码:
#include <cstdio>
#include <algorithm>
#include <map>
#include <cctype>
using namespace std;

int n,m;
char s[11],ch;
int com[101][101],num[101],sn;
map<string,bool> mp[101];
int main() {
    scanf("%d",&n);
    for(int i = 1;i <= n;i ++) {
        while((ch = tolower(getchar())) != '#') {
            if(ch >= 'a' && ch <= 'z') {
                if(sn < 10) s[sn ++] = ch;
            }
            else {
                s[sn] = 0;
                if(sn > 2) mp[i][s] = 1;
                sn = 0;
            }
        }
        for(map<string,bool>::iterator it = mp[i].begin();it != mp[i].end();it ++) {
            for(int j = 0;j < i;j ++) {
                com[i][j] = com[j][i] += mp[j][it -> first];
            }
        }
        com[i][i] = num[i] = mp[i].size();
    }
    scanf("%d",&m);
    int a,b;
    for(int i = 0;i < m;i ++) {
        scanf("%d%d",&a,&b);
        printf("%.1f%%\n",com[a][b] * 100.0 / (num[a] + num[b] - com[a][b]));
    }
}