当前位置: 首页 > article >正文

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

编写正排索引

继续编写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;     //官网文档urluint64_t dic_id;     //文档的ID}struct InvertedElem{uint64_t doc_id;std::string word;int weight;}//倒排拉链typedef std::vector<InvertedElem> InvertedList;class Index{private://正排索引的数据结构用数组,数组的下标天然是文档的IDstd::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.txtbool 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 debugcontinue;}BuildInvertedIndex(*doc);}return true;}private:DocInfo *BuildForwardIndex(const std::string &line){//1.解析line,字符串切分//line -> 3 string, title, content, urlstd::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]; //titledoc.content = results[1]; //contentdoc.url = results[2]; //urldoc.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 splitboost::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, urlstd::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]; //titledoc.content = results[1]; //contentdoc.url = results[2]; //urldoc.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;     //官⽹⽂档urluint64_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;  0elem.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 splitboost::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);
}

相关文章:

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

编写正排索引 继续编写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;…...

在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…...

skywalking实现原理

SkyWalking 是一个开源的分布式应用性能监控&#xff08;APM&#xff09;系统&#xff0c;主要用于微服务、云原生应用的性能监控、追踪和故障诊断。其实现原理涉及多个核心模块和技术&#xff0c;以下是 SkyWalking 的实现原理概述&#xff1a; 1. 采集数据&#xff08;数据收…...

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 …...

Windows逆向工程入门之栈指令与核心机制深度解析

公开视频 -> 链接点击跳转公开课程博客首页 -> ​​​链接点击跳转博客主页 目录 Windows逆向工程入门&#xff1a;栈指令与核心机制深度解析 一、栈的核心概念与内存布局 二、栈操作指令详解 1. PUSH 与 POP 2. PUSHA/PUSHAD 与 POPA/POPAD 3. PUSHF/PUSHFD 与 P…...

腾讯混元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. 反转链表 题目…...

目标检测IoU阈值全解析:YOLO/DETR模型中的精度-召回率博弈与工程实践指南

一、技术原理与数学本质 IoU计算公式&#xff1a; IoU \frac{Area\ of\ Overlap}{Area\ of\ Union} \frac{A ∩ B}{A ∪ B}阈值选择悖论&#xff1a; 高阈值&#xff08;0.6-0.75&#xff09;&#xff1a;减少误检&#xff08;FP↓&#xff09;但增加漏检&#xff08;FN↑…...

免费大模型网站

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

【ISO 14229-1:2023 UDS诊断全量测试用例清单系列:第三节】

ISO 14229-1:2023 UDS诊断服务测试用例全解析&#xff08;安全访问0x27服务&#xff09; 作者&#xff1a;车端域控测试工程师 更新日期&#xff1a;2025-02-12 关键词&#xff1a;UDS安全访问、0x27服务、ISO 14229-1:2023、ECU安全验证 一、服务概述 安全访问服务&#xff0…...

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…...

React Hooks 的两个坑点

React Hooks 使用注意事项 Area: Hooks Date: February 10, 2025 Important: &#x1f31f;&#x1f31f;&#x1f31f; React Hooks 注意事项 要点&#xff1a; useState 的初始化值 只在第一次渲染时计算&#xff0c;并且这个值不会随着组件重新渲染而更新。useEffect 可…...

C语言的字符串偏移小记

通过C的指针&#xff0c;我们可以遍历一个很长的字符串。我们针对这个字符串可以按照字符串里面的终止符做切分。 首先我们来看下面的一段代码&#xff1a; #include <stdio.h> #include <stdlib.h> #include <stdio.h> #include <string.h>const ch…...

Python学习心得正则表达式及re模块的使用

一、正则表达式定义以及正则表达式的构成&#xff1a; 1.什么式正则表达式&#xff1a; 正则表达式&#xff1a;是一个比较特殊的字符序列&#xff0c;能够帮助用户检查一个字符串是否符合某种特殊的模式。 2.正则表达式的构成&#xff1a; 正则表达式是由元字符和限定字符…...

Oracle启动与关闭(基础操作)

11g读取参数文件的顺序 9i之前&#xff0c;只有静态参数文件pfile文件。 9i开始&#xff0c;引入了动态参数文件spfile文件。 Windows&#xff1a; %ORACLE_HOME%\database SPFILEORCL就是动态参数文件 Linux&#xff1a; $ORACLE_HOME/dbs 11g中&#xff0c;启动数据库。…...

第二月:学习 NumPy、Pandas 和 Matplotlib 是数据分析和科学计算的基础

以下是一个为期 **1 个月&#xff08;30 天&#xff09;**的详细学习计划&#xff0c;精确到每天的学习内容和练习作业&#xff0c;帮助你系统地掌握 NumPy、Pandas 和 Matplotlib 的核心功能。 第 1 周&#xff1a;NumPy 基础 Day 1&#xff1a;NumPy 简介与数组创建 学习内…...