7-44 基于词频的文件相似度

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

输入格式:

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

Code~

#include <iostream>
#include <vector>
#include <set>
#include <algorithm>

using namespace std;

int main()
{
    int m, n, a, b;
    cin >> n;
    vector<set<string>> files(n, set<string>());
    char c = getchar();
    for (size_t i = 0; i < n; ++i)
    {
        string s = "";
        while ((c = getchar()) != '#')
        {
            if (isalpha(c))
                s += c;
            else
            {
                if (s.size() < 3)
                {
                    s = "";
                    continue;
                } else if (s.size() > 10)
                    s = s.substr(0, 10);
                transform(s.begin(), s.end(), s.begin(), ::tolower);
                files[i].insert(s);
                s = "";
            }
        }
    }
    cin >> m;
    for (size_t i = 0; i < m; ++i)
    {
        cin >> a >> b;
        set<string> inter;
        set_intersection(files[a - 1].begin(), files[a - 1].end(), files[b - 1].begin(), files[b - 1].end(),
                         inserter(inter, inter.begin()));
        printf("%.1f%%\n", inter.size() * 100.0 / (files[a - 1].size() + files[b - 1].size() - inter.size()));
        inter.clear();
    }
}

Ω 一些说明:

1.基本思想:一个文件中所有的有效单词用set进行存储,各个文件的set用一个vector进行存储。对于任意两个文件公共词汇个数的求取,是直接求两个文件set的交集(set_intersection,from < algorithm >)的个数。

2.由于不分大小写,因此存入的单词统一转为相应的小写单词存入。这里采用的是transform(s.begin(), s.end(), s.begin(), ::tolower)方法,将tolower函数应用于s的每个字符。

3.tolower函数之前有“::”是因为这个函数既有C版本的,又有STL模板的,二者存在冲突。这里用定界符强制指定为C版本的。

4.set_intersect函数可以求取两个set的交集,另外还有set_union(取并集)、set_difference(取差集)、set_symmetric_difference(取对称差集)等函数。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值