在信息检索中,单词的文档频率(Document Frequency,简称DF)是评估单词重要性的重要参数。针对一组文档,某个单词w的DF定义为该单词出现的文档的个数。注意:不是单词在这组文档中出现的总次数,而是包含该单词的文档的个数。若一篇文档包含某个单词多次,DF不重复计数。例如:如果w在10篇文档中出现过,其DF的值为10。 此外,由于同一个单词可能会有不同的大小写形态,需要将单词都归一化为小写形态后再进行DF的统计。 请你设计一个简易的单词统计程序,输入D篇文档,统计文档频率DF最大的前k个归一化为小写后的单词。对于结果中DF相同的单词,按其字典序排序。 请使用string类和自定义的Stool工具类完成本题目。#注意#,你的代码中不必包含对下图所示头文件的引用,更不需要如此前任务要求的那样,去实现其中的成员函数。它已经实现,并将被自动添加到你提交的代码中。你只需按其功能接口说明,正确调用即可。 第一行为两个数字D和K,中间以空格分隔, 以下D行每行一个英文文档(字符长度小于1000),单词之间以空格分隔 共K行,每行先输出归一化的单词,再输出其文档频率,中间以空格分隔。
时间: 2023-05-30 19:01:47 浏览: 152
这道题目要求我们设计一个简易的单词统计程序,输入D篇文档,统计文档频率DF最大的前k个归一化为小写后的单词。我们需要注意的是,同一个单词可能会有不同的大小写形态,需要将单词都归一化为小写形态后再进行DF的统计。同时,对于结果中DF相同的单词,需要按其字典序排序。
为了实现这个程序,我们可以先定义一个函数,用于将单词归一化为小写形态:
string toLower(string str) {
for (int i = 0; i < str.size(); i++) {
if (str[i] >= 'A' && str[i] <= 'Z') {
str[i] = str[i] - 'A' + 'a';
}
}
return str;
}
接下来,我们可以定义一个map,用于存储每个单词在多少篇文档中出现过:
map<string, int> df;
然后,我们可以遍历每篇文档,对于每个单词,先进行小写形态归一化,然后将其加入到df中:
for (int i = 0; i < D; i++) {
string doc = readDoc(); // 读取一篇文档
set<string> words; // 用set来去重
stringstream ss(doc);
string word;
while (ss >> word) {
word = toLower(word); // 将单词归一化为小写形态
words.insert(word); // 将单词加入set中去重
}
for (string w : words) {
df[w]++; // 将单词在df中的计数加1
}
}
最后,我们可以使用一个vector,将df中的所有单词按照DF值从大到小排序,并取前k个:
vector<pair<string, int>> sorted_df(df.begin(), df.end());
sort(sorted_df.begin(), sorted_df.end(), [](pair<string, int> a, pair<string, int> b) {
if (a.second == b.second) {
return a.first < b.first; // 如果DF相同,按照字典序排序
} else {
return a.second > b.second; // 否则按照DF值从大到小排序
}
});
for (int i = 0; i < k; i++) {
cout << sorted_df[i].first << endl; // 输出前k个单词
}
这样,我们就完成了这道题目的设计。需要注意的是,我们需要使用string类和自定义的Stool工具类完成本题目。
阅读全文