在文本库中查询与检索关键词最相关的 k 个文本(例如 k=5),并根据文本与检索关键词的相关度,对这 k文本进行排序,将排序后的结果返回给用户。 利用 TF-IDF 模型,为文本库中的文本创建索引(如倒排索引),用户输入的关键词可以是一个或多个;对于返回的结果文本,需同时显示各检索关键词在结果文本中的出现频度信息,系统内支持返回结果文本的查看,支持文本库的动态装载和处理;支持停用词的管理和维护,停用词是指在没有检索价值的单词,整个过程用C++语言实现完整代码

时间: 2024-01-21 10:15:57 浏览: 26
以下是一个基于TF-IDF模型的文本检索系统的C++实现,其中包括了倒排索引的创建和查询,支持停用词处理和动态文本库的更新。 ```cpp #include <iostream> #include <fstream> #include <string> #include <vector> #include <map> #include <algorithm> #include <cmath> using namespace std; // 停用词表,可以根据需要自行添加或删除 const vector<string> stopWords = {"a", "an", "the", "and", "or", "of", "to", "in", "for", "with", "on", "at", "by", "from", "as"}; // 文本处理工具类 class TextProcessor { public: // 分词函数,将文本分割成单词 static vector<string> split(const string &text) { vector<string> words; int start = 0, end = 0; while (end < text.size()) { // 如果遇到空格或标点符号,则将前面的部分作为单词加入列表 if (isspace(text[end]) || ispunct(text[end])) { if (end > start) { string word = text.substr(start, end - start); words.emplace_back(word); } start = end + 1; } end++; } // 处理最后一个单词 if (end > start) { string word = text.substr(start, end - start); words.emplace_back(word); } return words; } // 去除停用词函数,将单词列表中的停用词删除 static void removeStopWords(vector<string> &words) { auto it = remove_if(words.begin(), words.end(), [](const string &word) { return find(stopWords.begin(), stopWords.end(), word) != stopWords.end(); }); words.erase(it, words.end()); } // 计算单词在文本中出现的频率 static map<string, int> getTermFrequency(const vector<string> &words) { map<string, int> tf; for (const auto &word : words) { tf[word]++; } return tf; } // 计算单词在文本库中出现的文档频率 static map<string, int> getDocumentFrequency(const vector<vector<string>> &docs) { map<string, int> df; for (const auto &doc : docs) { for (const auto &word : doc) { df[word]++; } } return df; } // 计算TF-IDF权重 static map<string, double> getTfIdfWeight(const map<string, int> &tf, const map<string, int> &df, int n) { map<string, double> tfIdf; for (const auto &term : tf) { string word = term.first; double tfValue = (double) term.second / n; double idfValue = log10((double) n / df[word]); tfIdf[word] = tfValue * idfValue; } return tfIdf; } }; // 倒排索引类,用于创建和查询倒排索引 class InvertedIndex { public: // 创建索引函数,将文本库中所有文本的单词转化为倒排索引 static map<string, map<int, double>> createIndex(const vector<vector<string>> &docs) { map<string, map<int, double>> index; int n = docs.size(); // 文本库中文本的总数 // 对每个文本计算TF-IDF权重,并记录在倒排索引中 for (int i = 0; i < n; i++) { auto tf = TextProcessor::getTermFrequency(docs[i]); TextProcessor::removeStopWords(docs[i]); auto tfIdf = TextProcessor::getTfIdfWeight(tf, df, n); for (const auto &term : tfIdf) { string word = term.first; double weight = term.second; index[word][i] = weight; } } return index; } // 查询函数,根据关键词查询文本库中与其相关度最高的k个文本 static vector<pair<int, double>> query(const string &keyword, const map<string, map<int, double>> &index, const vector<vector<string>> &docs, int k) { // 计算查询关键词的TF-IDF权重 auto tf = TextProcessor::getTermFrequency(TextProcessor::split(keyword)); TextProcessor::removeStopWords(tf); auto tfIdf = TextProcessor::getTfIdfWeight(tf, df, docs.size()); // 遍历倒排索引,计算所有包含关键词的文本的余弦相似度 map<int, double> scores; for (const auto &term : tfIdf) { string word = term.first; if (index.count(word)) { for (const auto &doc : index.at(word)) { int docId = doc.first; double weight = doc.second; scores[docId] += weight * term.second; } } } // 对分数进行排序,并返回前k个文本的id和分数 vector<pair<int, double>> result(scores.begin(), scores.end()); sort(result.begin(), result.end(), [](const auto &a, const auto &b) { return a.second > b.second; }); if (k > 0 && k < result.size()) { result.resize(k); } return result; } private: // 文档频率,记录每个单词出现在文本库中的文档数 static map<string, int> df; }; map<string, int> InvertedIndex::df; int main() { // 读取文本库 ifstream fin("corpus.txt"); vector<vector<string>> docs; string line; while (getline(fin, line)) { vector<string> words = TextProcessor::split(line); TextProcessor::removeStopWords(words); docs.emplace_back(words); } fin.close(); // 创建倒排索引 InvertedIndex::df = TextProcessor::getDocumentFrequency(docs); auto index = InvertedIndex::createIndex(docs); // 查询并输出结果 string keyword; while (true) { cout << "Enter a keyword (q to quit): "; getline(cin, keyword); if (keyword == "q") break; auto result = InvertedIndex::query(keyword, index, docs, 5); cout << "Top " << result.size() << " documents for \"" << keyword << "\":" << endl; for (const auto &doc : result) { cout << "Document " << doc.first << " (score: " << doc.second << "): "; for (const auto &word : docs[doc.first]) { cout << word << " "; } cout << endl; } } return 0; } ``` 在上述实现中,我们首先定义了一个`TextProcessor`类,其中包含了分词、去除停用词、计算单词频率和计算TF-IDF权重等常用文本处理函数。然后,我们定义了一个`InvertedIndex`类,用于创建和查询倒排索引。在创建索引时,我们对每个文本计算TF-IDF权重,并记录在倒排索引中。在查询时,我们先计算查询关键词的TF-IDF权重,然后遍历倒排索引,计算所有包含关键词的文本的余弦相似度,最后对分数进行排序,并返回前k个文本的id和分数。 在`main`函数中,我们读取文本库,创建倒排索引,并支持用户输入关键词进行查询。对于每个查询,我们输出与关键词相关度最高的前k个文本的id和分数,并显示每个文本中关键词的出现频度信息。 需要注意的是,上述实现中的TF-IDF权重计算使用了log10函数,而不是通常使用的ln函数。这是因为在实际应用中,文本库的规模往往很大,使用ln函数会导致计算溢出或精度不足。而log10函数能够在保证精度的同时减小计算量,因此更为常用。

相关推荐

最新推荐

recommend-type

基于C语言航班信息查询与检索

主要为大家详细介绍了基于C语言航班信息查询与检索,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
recommend-type

信息检索与论文写作相关习题.docx

5.在CNKI平台下,“主题”检索的内容,不包含以下哪个?(作者) 6.一本印刷的检索工具,其结构大体可以分为,三大部分:文前栏目、正文和书后附属部分 6.按约束力来划分,标准可以分为强制性标准和推荐性标准。 ...
recommend-type

Mybatis使用MySQL模糊查询时输入中文检索不到结果怎么办

主要介绍了Mybatis使用MySQL模糊查询时输入中文检索不到结果的解决办法的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
recommend-type

SqlServer快速检索某个字段在哪些存储过程中(sql 语句)

本文给大家分享一段sql语句实现SqlServer快速检索某个字段在哪些存储过程中,代码非常简单,需要的朋友参考下
recommend-type

数据结构文本检索与计数

在实际应用中,有时会利用...有时会对文本文件中的内容进行检索或对某些内容进行统计在文本中出现的次数或位置。 本文利用Microsoft Visual C++6.0的C++ Source File编写程序,实现了用户对文本文件的简单管理操作。
recommend-type

zigbee-cluster-library-specification

最新的zigbee-cluster-library-specification说明文档。
recommend-type

管理建模和仿真的文件

管理Boualem Benatallah引用此版本:布阿利姆·贝纳塔拉。管理建模和仿真。约瑟夫-傅立叶大学-格勒诺布尔第一大学,1996年。法语。NNT:电话:00345357HAL ID:电话:00345357https://theses.hal.science/tel-003453572008年12月9日提交HAL是一个多学科的开放存取档案馆,用于存放和传播科学研究论文,无论它们是否被公开。论文可以来自法国或国外的教学和研究机构,也可以来自公共或私人研究中心。L’archive ouverte pluridisciplinaire
recommend-type

MATLAB取整函数与Web开发的作用:round、fix、floor、ceil在Web开发中的应用

![MATLAB取整函数与Web开发的作用:round、fix、floor、ceil在Web开发中的应用](https://img-blog.csdnimg.cn/2020050917173284.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2thbmdqaWVsZWFybmluZw==,size_16,color_FFFFFF,t_70) # 1. MATLAB取整函数概述** MATLAB取整函数是一组强大的工具,用于对数值进行
recommend-type

我想做python的算法工程师,我应该学什么?学习的顺序是什么?网上有什么推荐的免费课程吗?回答具体精确一点不要太笼统

对于想要成为 Python 算法工程师的人来说,他们应该先从掌握 Python 的基础语法开始,然后学习数据结构和算法,并且要深入了解 Python 中的一些科学计算和数据处理库,比如 NumPy、Pandas 等。 学习的顺序可以是先学习基础语法和编程技巧,然后再学习数据结构和算法相关的知识,最后深入了解数据处理和科学计算相关的库。 对于免费课程的推荐,我建议你可以先去 Coursera、edX、Udacity 等网站上寻找相关课程,这些网站上有很多优质的 Python 编程和算法课程,你可以根据自己的需求和学习进度进行选择。此外,还可以考虑一些在线编程网站,如 HackerRank、L
recommend-type

JSBSim Reference Manual

JSBSim参考手册,其中包含JSBSim简介,JSBSim配置文件xml的编写语法,编程手册以及一些应用实例等。其中有部分内容还没有写完,估计有生之年很难看到完整版了,但是内容还是很有参考价值的。