C++如何使用Simhash进行文件查重

大墨姑娘_3250

大墨姑娘_3250

2026-09-13

882人浏览

原创

simhash 是语义敏感的指纹算法,需先将文件转为文本再分词加权生成指纹;直接对二进制操作会导致分词失效、海明距离无意义。

c++如何使用simhash进行文件查重

Simhash 是什么,为什么不能直接对文件二进制做 simhash

Simhash 不是哈希校验,也不是加密摘要;它本质是一个**语义敏感的指纹算法**,依赖文本分词 + 权重统计 + 降维投票。直接对 std::ifstream 读出的 raw bytes 做 simhash,结果完全不可比——因为哪怕一个字节偏移,所有分词全乱,海明距离失去意义。

所以真正可行的路径只有一条:把文件当作**文本内容处理**(或先提取文本),再走标准 simhash 流程。若文件是 PDF/DOCX,得先用 popplerlibreoffice --headless 转文本;纯文本文件则可跳过这步。

用 C++ 实现 Simhash 的核心三步(不依赖第三方库)

标准 simhash 算法共三步:分词 → 加权哈希 → 指纹生成。C++ 中没有内置分词器,需手动处理:

  • 分词:按空白和标点切分,过滤停用词(如 "the", "a", "and"),保留长度 ≥2 的词;用 std::unordered_set 存停用词表
  • 加权哈希:对每个词调用 std::hash<:string>()</:string> 得 64 位 hash,再根据词频(或 TF-IDF)决定该 hash 向量每个 bit 是 +weight 还是 -weight
  • 指纹生成:对 64 维向量每维求和,最后用符号函数转为 0/1:(sum[i] >= 0) ? 1 : 0,拼成 uint64_t

示例关键片段:

C++ 算法竞赛自动化测试数据生成与校验框架
C++ 算法竞赛自动化测试数据生成与校验框架

根据原题生成新题面、验证器及完整测试数据,自动套用 testlib 模板,用于用户要求生成测试数据时。

下载
uint64_t simhash(const std::vector<:string>& words, const std::vector<int>& weights) {
    std::vector<int64_t> v(64, 0);
    for (size_t i = 0; i {}(words[i]);
        for (int b = 0; b > b) & 1) ? weights[i] : -weights[i];
        }
    }
    uint64_t f = 0;
    for (int b = 0; b = 0) f |= (1ULL 

<h3>计算两个文件 simhash 的海明距离(注意整数类型和 bit 顺序)</h3>
<p>simhash 查重靠的是海明距离小 ≠ 内容相似,但距离 ≤3 通常意味着高度重复。C++ 中别用 <code>__builtin_popcountll</code> 前忘了 cast 到 <code>unsigned long long</code>——MSVC 和 GCC 对负数行为不一致。</p>
<ul>
<li>正确写法:<code>int dist = __builtin_popcountll(a ^ b)</code>,其中 <code>a</code> 和 <code>b</code> 都是 <code>uint64_t</code>
</li>
<li>Windows 下若编译报错,改用 <code>std::bitset(a ^ b).count()</code>(稍慢但跨平台)</li>
<li>注意:simhash 对短文本(file_size  字节的文件</li>
</ul>
<h3>实际查重时必须加的工程细节</h3>
<p>直接两两比对 O(n²) 肯定崩,尤其上万文件。必须引入局部敏感哈希(LSH)加速:</p>
<ul>
<li>把 64 位指纹拆成 4 组 16 位前缀,分别存入 4 个 <code>std::unordered_map<uint16_t std::vector>></uint16_t></code>(key 是前缀,value 是文件 ID 列表)</li>
<li>查重时,对目标文件的 simhash 取 4 个 16 位段,合并所有对应桶里的候选文件 ID,去重后逐一算海明距离</li>
<li>别省略归一化:英文要转小写、去标点;中文需先用 ICU 或 cppjieba 分词,不能按字切</li>
</ul>
<p>最容易被忽略的一点:simhash 对排版差异(换行、缩进、空格数量)鲁棒,但对同义词替换(如 "buy" ↔ "purchase")完全无感——这不是 bug,是设计使然。真要覆盖语义,得上 sentence-transformers,simhash 只管“表面重复”。</p></int64_t></int></:string>

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
c++和c语言的区别有哪些
c++和c语言的区别有哪些

c++和c语言的区别:1、面向对象编程(OOP)支持不同;2、新增特性不同;3、标准库不同;4、编译方式不同;5、命名空间不同等等。想了解更多c++的相关内容,可以阅读本专题下面的文章。

2024.03.14

2068

9

c++和python学习顺序推荐
c++和python学习顺序推荐

一般建议先学习C++,再学习Python,因为这样可以逐步从较为底层的编程语言向更高级的语言过渡。想了解更多python的相关内容,可以阅读本专题下面的文章。

2024.03.14

939

6

python和c++学习性价比分析
python和c++学习性价比分析

Python易于学习,广泛应用于Web开发、数据科学和人工智能等领域,但性能较低。C语言性能高,适用于对性能要求较高的场景,如游戏开发和系统编程,但学习曲线陡峭,错误处理复杂。想了解更多python的相关内容,可以阅读本专题下面的文章。

2024.03.14

367

5

c语言和c++一样吗
c语言和c++一样吗

c语言和c++是两种不同的编程语言,虽然有相似之处,但存在显著差异。c语言专注于过程式编程和系统级开发,以简洁、高效著称。c++作为c语言的超集,引入了面向对象编程,增强了代码组织和管理能力,但学习曲线也更陡峭。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

307

5

c语言和c++先学哪个好
c语言和c++先学哪个好

初学者选择学习c语言还是c++语言,需要根据个人学习目标、背景以及编程兴趣和预期应用方向来决定。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

346

5

c语言和c++的区别和联系
c语言和c++的区别和联系

c语言和c++是计算机科学领域应用广泛的编程语言。虽然它们有着相似的基础,但它们在语言类型、语法功能和内存管理方面存在着显著差异。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

560

5

c++软件中文更改教程
c++软件中文更改教程

对于 ide,可通过打开设置,找到语言设置,选择中文,并保存更改。对于非 ide 应用程序,可查找设置或选项,选择语言设置,更改为中文,并保存更改。想了解更多c++的相关内容,可以阅读本专题下面的文章。

2024.03.21

1389

9

python和java和c++学习性价比分析
python和java和c++学习性价比分析

Python以其易学性、丰富的库和活跃的社区而著称,适合数据科学、人工智能和Web开发。Java以其跨平台性、企业级应用开发和Android应用开发而闻名。C++以其底层控制能力、高效性能和游戏开发而著称。选择哪种语言取决于个人兴趣、职业方向和特定需求。想了解更多python和java和c++的相关内容,可以阅读本专题下面的文章。

2024.03.22

1177

7

c++和c语言学习顺序推荐
c++和c语言学习顺序推荐

对于初学者,建议先学习C语言,掌握编程基础后再转入C++,便于理解面向对象编程概念。有编程经验者可直接学习C++,快速接触高级编程技术。想了解更多c++和c语言的相关内容,可以阅读本专题下面的文章。

2024.03.25

1305

9

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Valgrind Quick Start Guide
Valgrind Quick Start Guide

共0课时 | 0人学习

CLion CMake 快速入门教程
CLion CMake 快速入门教程

共0课时 | 0人学习