字符串的模糊匹配方法介绍

目录

  • 字符串的模糊匹配方法介绍
    • 一、编辑距离(Levenshtein Distance)
      • 复杂度分析
    • 二、Jaro-Winkler 距离
      • 复杂度分析
    • 三、最长公共子序列(LCS)
      • 复杂度分析
    • 四、模糊搜索(Fuzzy Search)
      • 复杂度分析
    • 五、正则表达式
      • 复杂度分析
    • 六、第三方库
      • 复杂度分析
    • 总结

在日常开发和数据处理中,我们经常会遇到需要判断两个字符串是否“相似”或“接近”的场景,这时就需要用到字符串的模糊匹配。模糊匹配不同于精确匹配,它允许一定程度的误差,比如拼写错误、字符缺失等。下面介绍几种常见的字符串模糊匹配方法。

一、编辑距离(Levenshtein Distance)

编辑距离是最常用的模糊匹配算法之一。它表示将一个字符串变换成另一个字符串所需的最少编辑操作次数。允许的操作包括插入、删除和替换一个字符。编辑距离越小,两个字符串越相似。

示例:

  • “kitten” 和 “sitting”的编辑距离为3(k→s,e→i,末尾加g)。

JavaScript代码示例:

// 计算Levenshtein距离的简单实现
function levenshtein(s1, s2) {const m = s1.length, n = s2.length;const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));for (let i = 0; i <= m; i++) dp[i][0] = i;for (let j = 0; j <= n; j++) dp[0][j] = j;for (let i = 1; i <= m; i++) {for (let j = 1; j <= n; j++) {if (s1[i - 1] === s2[j - 1]) {dp[i][j] = dp[i - 1][j - 1];} else {dp[i][j] = 1 + Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]);}}}return dp[m][n];
}
console.log(levenshtein('kitten', 'sitting')); // 输出: 3

复杂度分析

  • 时间复杂度:O(mn),其中 m 和 n 分别为两个字符串的长度。
  • 空间复杂度:O(mn),需要一个 m×n 的二维数组。

二、Jaro-Winkler 距离

Jaro 距离和 Jaro-Winkler 距离主要用于短字符串(如人名)的相似度比较。它考虑了字符的顺序和匹配字符之间的距离。Jaro-Winkler 在Jaro的基础上增加了前缀加权,使得前缀相同的字符串相似度更高。

JavaScript代码示例(使用jaro-winkler库):

// 需先安装 jaro-winkler: npm install jaro-winkler
const jaroWinkler = require('jaro-winkler');
console.log(jaroWinkler('MARTHA', 'MARHTA')); // 输出: 0.961...

复杂度分析

  • 时间复杂度:O(n),n 为字符串长度(Jaro-Winkler 算法通常用于较短字符串,效率较高)。
  • 空间复杂度:O(n)。

三、最长公共子序列(LCS)

最长公共子序列是指在不改变字符顺序的前提下,两个字符串中最长的公共子序列。LCS长度越长,字符串越相似。常用于DNA序列比对等场景。

JavaScript代码示例:

// 计算最长公共子序列长度
function lcs(s1, s2) {const m = s1.length, n = s2.length;const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));for (let i = 1; i <= m; i++) {for (let j = 1; j <= n; j++) {if (s1[i - 1] === s2[j - 1]) {dp[i][j] = dp[i - 1][j - 1] + 1;} else {dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);}}}return dp[m][n];
}
console.log(lcs('abcdef', 'acbcf')); // 输出: 4

复杂度分析

  • 时间复杂度:O(mn),m 和 n 为两个字符串的长度。
  • 空间复杂度:O(mn)。

四、模糊搜索(Fuzzy Search)

模糊搜索常用于搜索引擎和自动补全。常见实现有:

  • Trie树结合模糊匹配
  • BK-Tree(Burkhard-Keller Tree),适合大规模字符串集合的模糊查找
  • SimHash、MinHash等哈希算法,用于大规模文本的相似性检测

JavaScript代码示例(使用fuse.js库):

// 需先安装 fuse.js: npm install fuse.js
const Fuse = require('fuse.js');
const list = ['apple pie', 'banana', 'pineapple', 'apple', 'apricot'];
const fuse = new Fuse(list, { includeScore: true });
const result = fuse.search('apple pi');
console.log(result);

复杂度分析

  • Trie树:构建时间 O(NL),查询时间 O(L),N 为词条数,L 为平均长度。
  • BK-Tree:查询时间与误差阈值和数据分布有关,通常远优于暴力搜索。
  • SimHash/MinHash:构建和查询均为 O(L),L 为文本长度。
  • fuse.js(基于模糊搜索):O(NL),N 为数据量,L 为关键词长度。

五、正则表达式

正则表达式可以实现简单的模糊匹配,比如用通配符匹配部分字符,但它不适合复杂的相似度计算。

JavaScript代码示例:

const pattern = /ap.le/;
const text = 'apple';
if (pattern.test(text)) {console.log('匹配成功'); // 输出: 匹配成功
}

复杂度分析

  • 时间复杂度:O(n),n 为文本长度(正则表达式引擎实现不同,部分复杂模式可能更高)。
  • 空间复杂度:O(1)。

六、第三方库

许多编程语言都提供了现成的模糊匹配库。例如:

  • Python:fuzzywuzzy、difflib
  • JavaScript:fuse.js、jaro-winkler
  • Java:Lucene

JavaScript difflib 类似实现(使用string-similarity库):

// 需先安装 string-similarity: npm install string-similarity
const stringSimilarity = require('string-similarity');
const s1 = 'hello world';
const s2 = 'helo wrld';
console.log(stringSimilarity.compareTwoStrings(s1, s2)); // 输出: 0.909...

复杂度分析

  • fuzzywuzzy/difflib(Python):O(mn)
  • string-similarity(JS):O(mn)
  • fuse.js(JS):O(NL)
  • Lucene(Java):倒排索引,查询效率高,通常远优于 O(N)

总结

字符串的模糊匹配方法多种多样,选择合适的方法取决于具体的应用场景和性能需求。对于小规模、精度要求高的场景,可以使用编辑距离、Jaro-Winkler等算法;对于大规模数据检索,可以考虑BK-Tree、SimHash等高效算法。掌握这些方法,有助于提升文本处理和搜索的智能化水平。

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ActiveMQ在Spring Boot中的详细使用指南

📋 目录 🚀 ActiveMQ简介 什么是ActiveMQ? 核心概念 🏗️ 基础架构组件 📝 重要概念解释 ActiveMQ vs 其他消息中间件 🔧 环境搭建 1. ActiveMQ服务端安装 Docker方式(推荐初学者) 手动安装方式 2. 验证安装 访问Web管理界面 连接参数 测试连接 �…

二元一次方程

前言 最近刚学二元一次方程&#xff0c;想写一篇专栏熟悉一下本文写给初一的同学看&#xff0c;学过的就划了吧二元一次方程 两个未知数最高项次数为 111 次为整式方程二元一次方程的解不唯一&#xff0c;但是二元一次方程可以用一个未知数来表达另一个未知数eg:eg:eg: xy1x y…

AI编程的未来是智能体原生开发?

目录 前言 一、从“串行”到“并行”&#xff1a;什么是智能体原生开发&#xff1f; 1.1 传统模式&#xff08;串行思维&#xff09; 1.2 智能体原生模式&#xff08;并行思维&#xff09; 二、程序员的新角色&#xff1a;从代码手艺人到系统思想家 三、软件开发的终局&a…

【牛客刷题】小红的与运算

文章目录 一、题目介绍1.1 题目描述1.2 输入描述1.3 输出描述1.4 示例二、 解题思路2.1 核心算法设计2.2 性能优化关键2.3 算法流程图三、解法实现3.1 解法一:基础实现3.1.1 初级版本分析3.2 解法二:优化版本(推荐)3.2.1 优化版本分析四、总结与拓展4.1 关键优化技术4.2 算…

spring中 方法上@Transation实现原理

Spring中Transactional注解方法实现原理Spring的Transactional注解在方法级别实现事务管理的原理主要基于动态代理和拦截器机制&#xff0c;以下是其核心实现流程&#xff1a;1. 代理创建阶段当Spring容器启动时&#xff0c;会为带有Transactional注解的类创建代理对象&#xf…

qt-C++语法笔记之Stretch与Spacer的关系分析

qt-C语法笔记之Stretch与Spacer的关系分析 code review! 文章目录qt-C语法笔记之Stretch与Spacer的关系分析1. Stretch&#xff08;拉伸因子&#xff09;2. Horizontal Spacer 和 Vertical Spacer3. Stretch 和 Spacer 的关系4. 实际应用中的选择5. 注意事项6. 代码与 Qt Desig…

Qwen3技术综述

1. 引入 2025年5月&#xff0c;qwen推出了旗舰模型&#xff08;flagship model&#xff09;Qwen3-235B-A22B。并以Apache 2.0版权发布&#xff08;可自由商业使用&#xff0c;修改代码和商用要包含原始版权&#xff09;。本文对其技术报告中提到的数据处理技术与模型结构进行综…

[特殊字符] Excel 读取收件人 + Outlook 批量发送带附件邮件 —— Python 自动化实战

许多公司定期需要将不同部门或客户的报告发送给指定人员。手动操作容易出错、耗时且繁琐。今天这篇文章教你如何利用 Python 实现&#xff1a; &#x1f9e9; 从 Excel 中读取“收件人 抄送人 附件文件路径”&#xff1b; &#x1f4e4; 使用 win32com.client 调用 Outlook …

多模态大语言模型arxiv论文略读(152)

VidComposition: Can MLLMs Analyze Compositions in Compiled Videos? ➡️ 论文标题&#xff1a;VidComposition: Can MLLMs Analyze Compositions in Compiled Videos? ➡️ 论文作者&#xff1a;Yunlong Tang, Junjia Guo, Hang Hua, Susan Liang, Mingqian Feng, Xinya…

基于AR和SLAM技术的商场智能导视系统技术原理详解

本文面对室内定位算法工程师、智慧商场系统开发者、对VR/AR应用开发感兴趣的技术人员&#xff0c;解决如何通过SLAMAR技术破解大型商场室内导航的空间认知壁垒&#xff0c;实现沉浸式导览&#xff0c;本文提供完整技术方案与代码实现。 如需获取商场智能导视系统解决方案请前往…

Debezium日常分享系列之:认识Debezium Operator

Debezium日常分享系列之&#xff1a;认识Debezium Operator什么是Debezium OperatorDebezium Operator 的工作原理Debezium Operator 的优点Debezium Operator 使用场景Debezium Operator 的关键组件部署Debezium OperatorDebezium Operator 的使用什么是Debezium Operator De…

POSIX信号量,环形队列

是一种进程间或线程间同步机制&#xff0c;用于控制多个线程/进程对共享资源的访问&#xff0c;避免并发冲突。可以看作是一个计数器&#xff0c;通过对计数器的操作&#xff08;PV操作&#xff09;实现同步P操作(原子性)&#xff1a;&#xff0d;&#xff0d;&#xff0c;将信…

Python Day6

浙大疏锦行 Python Day6 内容&#xff1a; 描述性统计&#xff08;可视化分析&#xff09;单特征可视化&#xff08;连续、离散&#xff09;特征与标签可视化特征与特征可视化 代码&#xff1a; # TODO: 描述性统计 import pandas as pd import numpy as np import seaborn…

ESP32与树莓派C++、Rust开发实战

C++语言在ESP32、树莓派实例 以下是关于C++语言在ESP32、树莓派等硬件设备上的开发实例汇总,涵盖常见应用场景和代码示例。 ESP32开发实例 LED控制(GPIO操作) 使用ESP32的GPIO控制LED灯,示例代码基于Arduino框架: #include <Arduino.h> const int ledPin = 2; …

Jedis 原生之道:Redis 命令 Java 实现指南(一)

Hi~&#xff01;这里是奋斗的明志&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f331;&#x1f331;个人主页&#xff1a;奋斗的明志 &#x1f331;&#x1f331;所属专栏&#xff1a;Redis &#x1f4da;本系列文章为个人学习笔…

飞算 JavaAI 开发助手:深度学习驱动下的 Java 全链路智能开发新范式

飞算 JavaAI 开发助手&#xff1a;深度学习驱动下的 Java 全链路智能开发新范式 文章目录飞算 JavaAI 开发助手&#xff1a;深度学习驱动下的 Java 全链路智能开发新范式前言飞算 JavaAI IDEA插件下载、注册、使用智能引导操作流程Java Chat智能工作流程操作流程智能问答操作流…

Spring Boot 核心特性与版本演进解析

深度解读自动配置原理、版本差异与 3.x 的颠覆性变革 一、Spring Boot 的核心理念与迭代主线 Spring Boot 用两大核心武器重构了 Java 开发范式&#xff1a; 嵌入式容器&#xff1a;终结了 “war 包 Tomcat 配置地狱”&#xff0c;让 java -jar 成为生产级部署的标准姿势自动…

React Tailwind css 大前端考试、问卷响应式模板

功能概述 基于 React 和 Tailwind CSS 开发的在线大前端知识考试系统。页面设计简洁美观&#xff0c;交互流畅&#xff0c;适合前端开发者、学习者进行自我测试和知识巩固。系统内置多道涵盖 React、CSS、JavaScript、HTTP 等前端核心知识点的题目&#xff0c;支持单选与多选题…

【前端】手写代码汇总

近期更新完&#xff0c;后面不定期更新&#xff0c;建议关注收藏点赞。 目录快排手写防抖节流数组扁平化&#xff08;要求使用 reduce 方法&#xff09;数组filter实现手写一个加载图片的函数 loadImage手写Promise then手写 Promise.All手写 Promise.race手写allsettled手写us…

基于MATLAB 的心电信号去噪

基于Matlab的心电信号去噪 generate.m , 3450 genR.m , 953 genU.m , 891 get_obs.m , 957 CHANGELOG , 11185 find_localobs.m , 2312 fmain.m , 2272