6.编写正排索引切分字符串|倒排索引原理|引入jieba到项目(C++)

news2025/2/21 11:16:54
编写正排索引

继续编写incde.hpp

#pragma once

#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <unordered_map>
#include "util.hpp"

namespace ns_index{

	struct DocInfo{
		std::string title;   //文档标题
		std::string content; //文档对应的去标签之后的内容
		std::string url;     //官网文档url
		uint64_t dic_id;     //文档的ID
	}

	struct InvertedElem{
		uint64_t doc_id;
		std::string word;
		int weight;
	}

	//倒排拉链
	typedef std::vector<InvertedElem> InvertedList;

	class Index{
		private:
			//正排索引的数据结构用数组,数组的下标天然是文档的ID
			std::vector<DocInfo> forward_index; //正排索引
			//倒排索引一定是一个关键字和一组(个)InvertedElem对应[关键字和倒排拉链的映射关系]
			std::unordered_map<std::string, InvertedList> inverted_index;
		public:
			Index(){}
			~Index(){}
		public:
			//根据doc_id找到文档内容
			DocInfo *GetForwardIdex(uint64_t doc_id)
			{
				if(doc_id >= forward_index.size()){
						std::cerr << "doc_id out range, error" << std::endl;
						return nullptr;
				}
				return &forward_index[doc_id];
			}

			//根据关键字string获得倒排拉链
			InvertedList *GetInvertedList(const std::string &word)
			{
				auto iter = inverted_index.find(word);
				if(iter == inverted_index.end()){
						std::cerr << word << " have no InvertedList" << std::endl;
						return nullptr;
				}

				return &(iter->second);
			}
			//根据去标签,格式化之后的文档,构建正排和倒排索引
			//data/raw_html/raw.txt
			bool BuildIndex(const std::string &input) //parse处理完毕的数据交给我
			{
				std::ifstream in(input, std::ios::in | std::ios::binary);
				if(!in.is_open()){
					std::cerr << "sorry, " << input << " open error" << std::endl;
					return false;
				}

				std::string line;
				while(std::getline(in, line)){
					DocInfo * doc = BuildForwardIndex(line);
					if(nullptr == doc){
							std::cerr << "build " << line << " error" << std::endl; //for debug
							continue;
					}

					BuildInvertedIndex(*doc);
				}
				return true;
			}
		private:
			DocInfo *BuildForwardIndex(const std::string &line)
			{
				//1.解析line,字符串切分
				//line -> 3 string, title, content, url
				std::vector<std::string> results;
				const std::string sep = '\3';  //行内分隔符
				ns_util::StringUtil::CutString(line, &results, sep);
				if(results.size() != 3){
					return nullptr;
				}
				//2.字符串进行填充到DocInfo中
				DocInfo doc;
				doc.title = results[0]; //title
				doc.content = results[1]; //content
				doc.url = results[2]; //url
				doc.doc_id = forward_index.size(); //先保存id,再插入,对应的id就是当前doc在vector中的下标
				//3.插入到正排索引的vector中
				forward_index.push_back(doc);
			}

			bool BuildInvertedIndex(const DocInfo &doc)
			{

			}
	};

}

切分字符串

打开util.hpp

#pragma once
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <boost/algorithm/string.hpp>

namespace ns_util{
	class FileUtil{
		public:
			static bool ReadFile(const std::string &file_path, std::string *out)
			{
				std::ifstream in(file_path, std::ios::in);
				if(!in.is_open()){
					std::cerr << "open file" << file_path << " error" << std::endl;
					return false;
				}

				std::string line;
				while(std::getline(in, line)){ //如何理解getline读取到文件结束:getline的返回值是一个&,while判断的是一个bool类型,本质是因为返
回的对象当中重载了强制类型转化
					*out += line;
				}


				in.close();
				return true;
			}
	};
	class StringUtil{
		public:
			static void CutString(const std::string &target, std::vector<std::string> *out, const std::string &sep)
			{
				//boost split
				boost::split(*out, target, boost::is_any_of(sep), boost::token_compress_on); //打开压缩分隔符
			}
	};
}

打开index.hpp

DocInfo *BuildForwardIndex(const std::string &line)
{
	//1.解析line,字符串切分
	//line -> 3 string, title, content, url
	std::vector<std::string> results;
	const std::string sep = '\3';  //行内分隔符
	ns_util::StringUtil::CutString(line, &results, sep);
	if(results.size() != 3){
		return nullptr;
	}
	//2.字符串进行填充到DocInfo中
	DocInfo doc;
	doc.title = results[0]; //title
	doc.content = results[1]; //content
	doc.url = results[2]; //url
	doc.doc_id = forward_index.size(); //先保存id,再插入,对应的id就是当前doc在vector中的下标
	//3.插入到正排索引的vector中
	forward_index.push_back(doc);
	return &forward_index.back();
}

bool BuildInvertedIndex(const DocInfo &doc)
{
		//DocInfo{title, content, url, doc_id}
		//word -> 倒排拉链
		return true;
}
倒排索引原理
struct InvertedElem{  
	uint64_t doc_id;  
	std::string word;  
	int weight;  
};

倒排拉链

typedef std::vector<InvertedElem> InvertedList;  

倒排索引⼀定是⼀个关键字和⼀组(个)InvertedElem对应[关键字和倒排拉链的映射关系]

std::unordered_map<std::string, InvertedList> inverted_index;

我们拿到的⽂档内容

struct DocInfo{  
	std::string title;   //⽂档的标题
	std::string content; //⽂档对应的去标签之后的内容
	std::string url;     //官⽹⽂档url
	uint64_t doc_id;     //⽂档的ID,暂时先不做过多理解
};

⽂档:

title : 吃葡萄  
content: 吃葡萄不吐葡萄⽪  
url: http://XXXX  
doc_id: 123

根据⽂档内容,形成⼀个或者多个InvertedElem(倒排拉链)
因为当前我们是⼀个⼀个⽂档进⾏处理的,⼀个⽂档会包含多个”词“, 都应当对应到当前的doc_id

  1. 需要对 title && content都要先分词 --使⽤jieba分词
title: 吃/葡萄/吃葡萄(title_word)  
content:吃/葡萄/不吐/葡萄⽪(content_word)

词和⽂档的相关性(词频:在标题中出现的词,可以认为相关性更⾼⼀些,在内容中出现相关性低⼀些)
2. 词频统计

struct word_cnt{  
	title_cnt;  
	content_cnt;  
} 
unordered_map<std::string, word_cnt> word_cnt;  
for &word : title_word{  
	word_cnt[word].title_cnt++; //吃(1)/葡萄(1)/吃葡萄(1)  
} 
for &word : content_word {  
	word_cnt[word].content_cnt++; //吃(1)/葡萄(1)/不吐(1)/葡萄⽪(1)  
} 

知道了在⽂档中,标题和内容每个词出现的次数
3. 构建倒排拉链节点,⾃定义相关性

for &word : word_cnt{  
	//具体⼀个词和123⽂档的对应关系,当有多个不同的词,指向同⼀个⽂档的时候,此时该优先显⽰谁??相关性!  
	struct InvertedElem elem;  
	elem.doc_id = 123;  0
	elem.word = word.first;  
	elem.weight = 10*word.second.title_cnt + word.second.content_cnt; 
	inverted_index[word.first].push_back(elem);  
} 
jieba的安装和使⽤–cppjieba

克隆,复制网址链接
![[Pasted image 20250216094850.png]]

获取链接: git clone https://gitcode.net/mirrors/yanyiwu/cppjieba.git
![[Pasted image 20250216095310.png]]

如何使⽤:注意细节,我们需要⾃⼰执⾏:
cd cppjieba; cp -rf deps/limonp include/cppjieba/, 不然会编译报错

[whb@VM-0-3-centos test]$ ll  
total 372  
-rwxrwxr-x 1 whb whb 366424 Mar 28 12:11 a.out  
drwxrwxr-x 8 whb whb 4096 Mar 28 12:01 cppjieba
-rw-rw-r-- 1 whb whb  856 Mar 28 12:11 demo.cpp
lrwxrwxrwx 1 whb whb  13 Mar 28 12:05 dict -> cppjieba/dict
lrwxrwxrwx 1 whb whb  16 Mar 28 12:06 inc -> cppjieba/include
-rw-rw-r-- 1 whb whb  365 Mar 28 10:21 test.cc

[whb@VM-0-3-centos test]$ cat demo.cpp  
#include "inc/cppjieba/Jieba.hpp"  
#include <iostream>  
#include <string>  
#include <vector>  
using namespace std;

const char* const DICT_PATH = "./dict/jieba.dict.utf8";  
const char* const HMM_PATH = "./dict/hmm_model.utf8";  
const char* const USER_DICT_PATH = "./dict/user.dict.utf8";  
const char* const IDF_PATH = "./dict/idf.utf8";  
const char* const STOP_WORD_PATH = "./dict/stop_words.utf8";

int main(int argc, char** argv) {  
	cppjieba::Jieba jieba(DICT_PATH,  
	HMM_PATH,  
	USER_DICT_PATH,  
	IDF_PATH,  
	STOP_WORD_PATH);  
	vector<string> words;  
	string s;  
	s = "⼩明硕⼠毕业于中国科学院计算所,后在⽇本京都⼤学深造";  
	cout << s << endl;  
	cout << "[demo] CutForSearch" << endl;  
	jieba.CutForSearch(s, words);  
	cout << limonp::Join(words.begin(), words.end(), "/") << endl;  
	return EXIT_SUCCESS;  
} 
//编写倒排索引的代码  
//注意:建⽴倒排索引的时候,要忽略⼤⼩写!!
引入jieba到项目

把jieba作为工具,写入到util.hpp中

ln -s ./test/cppjieba/include/cppjieba cppjieba

![[Pasted image 20250216101909.png]]

ln -s ./test/cppjieba/dict dict

![[Pasted image 20250216102209.png]]

如果想取消链接可以使用unlink

打开util.hpp

#pragma once
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <boost/algorithm/string.hpp>
#include "cppjieba/Jieba.hpp"

namespace ns_util{
	class FileUtil{
		public:
			static bool ReadFile(const std::string &file_path, std::string *out)
			{
				std::ifstream in(file_path, std::ios::in);
				if(!in.is_open()){
					std::cerr << "open file" << file_path << " error" << std::endl;
					return false;
				}

				std::string line;
				while(std::getline(in, line)){ //如何理解getline读取到文件结束:getline的返回值是一个&,while判断的是一个bool类型,本质是因为返回的对象当中重载了强制类型转化
					*out += line;

				}


				in.close();
				return true;
			}
	};
	class StringUtil{
		public:
			static void CutString(const std::string &target, std::vector<std::string> *out, const std::string &sep)
			{
				//boost split
				boost::split(*out, target, boost::is_any_of(sep), boost::token_compress_on); //打开压缩分隔符
			}
	};

	const char* const DICT_PATH = "./dict/jieba.dict.utf8";
	const char* const HMM_PATH = "./dict/hmm_model.utf8";
	const char* const USER_DICT_PATH = "./dict/user.dict.utf8";
	const char* const IDF_PATH = "./dict/idf.utf8";
	const char* const STOP_WORD_PATH = "./dict/stop_words.utf8";

	class JiebaUtil{
		private:
			static cppjieba::Jieba jieba;
		public:
			static void CutString(const std::string &src, std::vector<std::string> *out)
			{
				jieba.CutForSearch(src, *out);
			}
	};

	cppjieba::Jieba JiebaUtil::jieba(DICT_PATH, HMM_PATH, USER_DICT_PATH, IDF_PATH, STOP_WORD_PATH);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2299609.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在Windows系统上测试safari浏览器的兼容性

文章目录 前言手机端的safari浏览器能替代PC端吗在Windows上测试safari浏览器的兼容性的方法利用云服务使用虚拟机在Windows上下载虚拟机遇到的问题以及解决思路总结 前言 在测试网站的兼容性时需要用到safari浏览器&#xff0c;在没有Mac的情况下&#xff0c;又不想麻烦同事&…

【设计模式】【结构型模式】桥接模式(Bridge)

&#x1f44b;hi&#xff0c;我不是一名外包公司的员工&#xff0c;也不会偷吃茶水间的零食&#xff0c;我的梦想是能写高端CRUD &#x1f525; 2025本人正在沉淀中… 博客更新速度 &#x1f44d; 欢迎点赞、收藏、关注&#xff0c;跟上我的更新节奏 &#x1f3b5; 当你的天空突…

惠普HP Color LaserJet CP1215/1210彩色打印机打印校准方法

执行校准 &#xff08;用随机光盘安装驱动&#xff09;完整安装打印机驱动程序。安装驱动程序的操作方法请参考以下文章&#xff1a; 惠普HP Color laserjet cp1215激光打印机在windows 7下使用随机光盘安装驱动程序&#xff0c;安装完成后&#xff1b; 依次点击“开始”→“所…

【雅思博客02】Virus!

Elementary ‐ Virus! (C0007) A: Oh great! This stupid computer froze again! That’s the third time today! Hey Samuel, can you come take a look at my PC? It’s acting up again. It must have a virus or something. B: Just give me a second; I’ll be right …

模型GPU->NPU(Ascend)迁移训练简述

目录 一、迁移训练流程图解 二、详细流程步骤 1. 模型训练与日志记录 2. 跨平台精度对齐对比 3. 问题定位与修复 4. 迭代验证 三、关键技术点 四、常见问题与解决方案 一、迁移训练流程图解 通过华为云的modelart进行运行环境选型 北京四使用GPU进行模型训练&#xff…

sql语言语法的学习

sql通用语法 sql分类 DDL(操作数据库和表) 操作数据库 操作表_查询 操作表_创建 举例&#xff1a; 操作表_删除 操作表_修改 DML(增删改表中数据) DML添加数据 DML删除数据

3.buuctf [BSidesCF 2019]Kookie

进入题目页面如下 尝试弱口令密码登录&#xff0c;无果 显示无效密码 用题中给出的用户名和密码登录虽然成功但没得到flag 用burp suite抓包试试 看到username处显示cookie 题目说用admin登录 将username的值改为admin 拿到flag 最后拿到flag

springboot245-springboot项目评审系统(源码+论文+PPT+部署讲解等)

&#x1f495;&#x1f495;作者&#xff1a; 爱笑学姐 &#x1f495;&#x1f495;个人简介&#xff1a;十年Java&#xff0c;Python美女程序员一枚&#xff0c;精通计算机专业前后端各类框架。 &#x1f495;&#x1f495;各类成品Java毕设 。javaweb&#xff0c;ssm&#xf…

Dify+Ollama+DeepSeek部署本地大模型+知识库搭建

前言 上一篇文章《OllamaDeepSeek部署本地大模型》我们已经知道如何在本地搭建自己的大模型了&#xff0c;不过想要让大模型能够根据我们个人或者企业的数据情况做出精准的回答&#xff0c;我们还需要将自己的数据投喂给大模型才可以。本篇文章我们将会使用一个开源项目dify集…

每日一题——不同路径的数目与矩阵最小路径和

机器人路径问题与矩阵最小路径和 1. 机器人路径问题题目描述示例示例 1示例 2 解题思路动态规划 代码实现复杂度分析 2. 矩阵的最小路径和题目描述示例示例 1示例 2 解题思路动态规划 代码实现复杂度分析 总结 1. 机器人路径问题 题目描述 一个机器人在 (m \times n) 大小的地…

143,【3】 buuctf web [GYCTF2020]EasyThinking

进入靶场 一开始那个题目名字就想到了框架 扫描目录 访问后自动下载了 找源码 <?php namespace app\home\controller;use think\exception\ValidateException; use think\facade\Db; use think\facade\View; use app\common\model\User; use think\facade\Request; use …

腾讯混元hunyuan3d生成模型,本地搭建和使用

腾讯混元hunyuan3d生成模型,本地搭建和使用 腾讯混元hunyuan3d生成模型,本地搭建和使用一. 话不多说,我们直接上本地部署的详细步骤1. 将仓库拉到本地2. 下载2个模型, 注意这里推荐 先使用conda创建环境后在安装modelscope进行下载模型2.1 关于第一个模型我们要在 Hunyuan3D-1 …

flutter image_cropper插件安装后 打包apk 报错命名空间问题

本篇文章主要讲解&#xff0c;Flutter安装完新依赖打包apk报错 A problem occurred configuring project ‘:image_cropper’. 命名空间问题的解决办法及原因说明。 日期&#xff1a;2025年2月15日 作者&#xff1a;任聪聪 一、报错现象&#xff1a; 报文信息&#xff1a; FAI…

2025-2-15-4.5 链表(基础题)

文章目录 4.6 链表&#xff08;基础题&#xff09;206. 反转链表92. 反转链表II24. 两两交换链表中的节点 4.6 链表&#xff08;基础题&#xff09; 有一天我做题忽然发现要把一个数组完全倒着翻过来很费劲&#xff0c;今天看&#xff0c;链表为此而生啊。 206. 反转链表 题目…

免费大模型网站

腾讯元宝 腾讯元宝 秘塔搜索 秘塔搜索 超算互联网 超算互联网回答速度很慢 Chatbot Arena Chatbot Arena 大模型竞技场。

macOS部署DeepSeek-r1

好奇&#xff0c;跟着网友们的操作试了一下 网上方案很多&#xff0c;主要参考的是这篇 DeepSeek 接入 PyCharm&#xff0c;轻松助力编程_pycharm deepseek-CSDN博客 方案是&#xff1a;PyCharm CodeGPT插件 DeepSeek-r1:1.5b 假设已经安装好了PyCharm PyCharm: the Pyth…

java八股文-mysql

1. 索引 1.1 什么是索引 索引(index)是帮助Mysql高效获取数据的数据结构(有序).提高数据的检索效率,降低数据库的IO成本(不需要全表扫描).通过索引列对数据进行排序,降低数据排序成本,降低了CPU的消耗. 1.2 mysql索引使用的B树? 1. 没有使用二叉树&#xff0c;最坏情况o&…

YOLO11环境搭建CUDA12.6

1.安装CUDA和cuDNN 1.1安装CUDA 1.1.1查看当前你的电脑显卡支持的最高CUDA版本,后面的安装不能超过它 通过命令的方式查看 输入nvidia-smi 1.1.2 下载CUDA 官网地址:CUDA Toolkit Archive | NVIDIA Developer 选择cuda_12.6.3 下载完成后,如下: 安装,一直下一步即可:…

OpenEuler学习笔记(三十二):在OpenEuler上搭建项目管理平台

在OpenEuler上搭建一个支持网页和手持访问、且支持用户功能自定义的项目管理平台&#xff0c;可以选择多种开源工具。以下是基于 Redmine 的搭建方案&#xff0c;Redmine 是一个灵活的项目管理工具&#xff0c;支持网页和移动端访问&#xff0c;并且可以通过插件扩展功能。 1.…

LabVIEW中的icon.llb 库

icon.llb 库位于 C:\Program Files (x86)\National Instruments\LabVIEW 2019\vi.lib\Platform 目录下&#xff0c;是 LabVIEW 系统中的一个重要库。它的主要功能是与图标相关的操作&#xff0c;提供了一些实用的 VI 用于处理 LabVIEW 图标的显示、修改和设置。通过该库&#x…