从古诗词到现代文:双向最大匹配算法(BM)在不同文本类型中的应用效果

从古诗词到现代文:双向最大匹配算法在不同文本类型中的实战效果剖析

如果你曾经尝试过让计算机理解一句中文,无论是“床前明月光”还是“我今天要去超市买点东西”,你很快就会遇到一个根本性的难题:词与词之间没有空格。这看似简单的问题,却是中文自然语言处理(NLP)的第一道门槛,也是决定后续所有任务质量的基础。分词,就是将连续的字序列切分成有意义的词语序列的过程。而在众多基于词典的分词方法中,双向最大匹配算法(Bi-directional Maximum Matching, BM) 因其简单、高效和相对可靠的特性,至今仍在许多场景下扮演着重要角色。

今天,我们不打算重复教科书上的算法定义,而是想深入一个更具体、也更有趣的领域:当我们将同一套算法,应用于古诗词现代文这两种语言风格迥异的文本时,会发生什么?古诗词凝练、多单字词、语法灵活;现代文直白、复合词多、结构清晰。这种差异对基于词典的匹配算法提出了截然不同的挑战。理解BM算法在这两种文本上的表现差异,不仅能帮助我们更好地使用它,更能让我们洞察中文语言的内在规律,以及算法设计的局限性。无论你是刚踏入NLP领域的新手,还是需要处理混合文本内容(如古籍数字化、文学分析)的研究者,这篇文章都将通过具体的案例对比和实战代码,带你一探究竟。

1. 重温核心:FMM、BMM与BM算法的本质

在深入对比之前,我们有必要快速厘清正向最大匹配(FMM)、逆向最大匹配(BMM)以及它们的结合体——双向最大匹配(BM)的核心逻辑。这不仅仅是概念回顾,更是理解其在不同文本上表现差异的基础。

正向最大匹配(FMM) 的思路非常直观:它像一个从左到右的“贪婪”阅读者。给定一个句子和一部词典,算法总是试图从当前句子的最左端开始,切分出词典中存在的最长可能的词。如果匹配失败,就缩短匹配长度,直到成功匹配到一个词或只剩下一个字。这个过程不断重复,直到扫描完整个句子。

def forward_maximum_matching(text, word_dict, max_len): """ 正向最大匹配分词 :param text: 待分词字符串 :param word_dict: 词典集合 :param max_len: 词典中最长词的长度 :return: 分词结果列表 """ result = [] index = 0 # 当前扫描起始位置 text_length = len(text) while index < text_length: matched = False # 从最大可能长度开始尝试 for length in range(min(max_len, text_length - index), 0, -1): word = text[index:index + length] if word in word_dict: result.append(word) index += length matched = True break # 如果未匹配到任何词,按单字切分 if not matched: result.append(text[index]) index += 1 return result 

与之相对,逆向最大匹配(BMM) 则是一个从右到左的“回溯者”。它从句子的末尾开始,尝试匹配最长的词。其基本流程与FMM对称,但方向相反。一个常见的误解是BMM仅仅是把句子倒过来用FMM处理。实际上,BMM在处理某些结构时,由于扫描方向的差异,会产生与FMM不同的切分结果。

那么,双向最大匹配(BM) 的策略就很明确了:它同时运行FMM和BMM,然后根据一套启发式规则选择更优的结果。这套规则通常遵循“颗粒度最大、非词典词和单字词最少”的原则,具体优先级如下:

  1. 比较分词数量:优先选择切分出的词语总数更少的那一个。这基于“长词优先”的假设。
  2. 数量相同时,比较单字词数量:选择结果中单字词(长度为1的词)更少的那一个。
  3. 若上述均相同,则任选一个(通常选择FMM的结果)。
def bidirectional_maximum_matching(text, word_dict, max_len): """ 双向最大匹配分词 :param text: 待分词字符串 :param word_dict: 词典集合 :param max_len: 词典中最长词的长度 :return: 分词结果列表 """ fmm_result = forward_maximum_matching(text, word_dict, max_len) bmm_result = backward_maximum_matching(text, word_dict, max_len) # 假设已实现BMM # 规则1:选择词数少的 if len(fmm_result) != len(bmm_result): return fmm_result if len(fmm_result) < len(bmm_result) else bmm_result # 规则2:词数相同时,选择单字词少的 fmm_single = sum(1 for word in fmm_result if len(word) == 1) bmm_single = sum(1 for word in bmm_result if len(word) == 1) if fmm_single != bmm_single: return fmm_result if fmm_single < bmm_single else bmm_result # 规则3:若都相同,默认返回FMM结果(或可根据其他规则选择) return fmm_result 
提示:这里的“最大匹配”指的是在当前位置,基于现有词典能匹配到的最长字符串,是一种局部最优的贪心策略。它无法解决所有的歧义问题,但其效率高、实现简单的特点,使其成为工程上的一个实用基线。</

Read more

Flutter 三方库 objectbox_generator — 自动化构建鸿蒙极速 NoSQL 数据库映射(适配鸿蒙 HarmonyOS Next ohos)

Flutter 三方库 objectbox_generator — 自动化构建鸿蒙极速 NoSQL 数据库映射(适配鸿蒙 HarmonyOS Next ohos)

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net。 Flutter 三方库 objectbox_generator — 自动化构建鸿蒙极速 NoSQL 数据库映射(适配鸿蒙 HarmonyOS Next ohos) 在高性能移动应用开发中,本地数据的持久化存储效率往往是决定用户感知流畅度的木桶短板。传统的 SQLite 虽然结构化程度高,但在处理大规模对象关系映射(ORM)时,复杂的 SQL 拼接和反射解析往往会成为性能瓶颈。 ObjectBox 作为一个专为移动设备打造的、跨平台的超高速 NoSQL 数据库,已经成为了许多追求极致体验开发者的首选。而在 Flutter for OpenHarmony 开发中,配合 objectbox_generator,我们可以通过注解驱动的自动化流程,掌握这套高性能数据库的核心用法。 ⚠️ 鸿蒙适配现状提示:截至本文撰写时,ObjectBox 的 Dart 插件尚未提供官方的 OpenHarmony

By Ne0inhk

Flutter 三方库 login_client 的鸿蒙化适配指南 - 打造工业级安全登录、OAuth2 自动化鉴权、鸿蒙级身份守门员

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 login_client 的鸿蒙化适配指南 - 打造工业级安全登录、OAuth2 自动化鉴权、鸿蒙级身份守门员 在鸿蒙跨平台应用的网络安全架构中,如何稳健地管理 OAuth2 访问令牌(Access Tokens)与刷新令牌(Refresh Tokens)是衡量应用成熟度的重要指标。如果你厌倦了在每个请求中手动判断 401 错误并递归刷新 Token。今天我们要聊的是 login_client——一个专门为简化现代身份认证流设计的 HTTP 客户端装饰器,正是帮你构建“无感登录、自动续期”体验的核心插件。 前言 login_client 是一套位于 http 或 oauth2 库之上的高阶封装。它的核心使命是:自动拦截未授权请求、静默刷新

By Ne0inhk
Flutter 组件 ansi_text 适配鸿蒙 HarmonyOS 实战:终端色彩渲染,构建高性能 ANSI 日志高亮与命令行交互架构

Flutter 组件 ansi_text 适配鸿蒙 HarmonyOS 实战:终端色彩渲染,构建高性能 ANSI 日志高亮与命令行交互架构

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 组件 ansi_text 适配鸿蒙 HarmonyOS 实战:终端色彩渲染,构建高性能 ANSI 日志高亮与命令行交互架构 前言 在鸿蒙(OpenHarmony)生态迈向工业级运维、涉及大量后台守护进程(Daemon)、系统日志审计及开发者工具链(CLI)开发的背景下,如何为枯燥的纯文本终端注入具备视觉层级的色彩与样式,已成为提升调试效率与故障定位速度的“视觉助推器”。在鸿蒙设备这类强调 AOT 极致性能与低级别 shell 交互的环境下,如果应用依然依赖基础的单色字符串输出日志,由于由于信息流极其庞大且缺乏重点,极易由于由于“视觉疲劳”导致关键系统警告或业务异常被淹没在海量数据中。 我们需要一种能够支持 ANSI 转义序列、具备富文本样式(加粗/背景色)且兼容多种终端模拟器的文本渲染方案。 ansi_text 为 Flutter 开发者引入了基于标准

By Ne0inhk
Flutter for OpenHarmony: Flutter 三方库 envied_generator 给鸿蒙应用的敏感 API Key 穿上“不可破解”的防护服(安全性加固利器)

Flutter for OpenHarmony: Flutter 三方库 envied_generator 给鸿蒙应用的敏感 API Key 穿上“不可破解”的防护服(安全性加固利器)

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net 前言 在进行 OpenHarmony 应用开发时,我们不可避免地要集成各种三方服务(如高德地图 KEY、Firebase Secret、或是鸿蒙分布式服务的授权 Token)。如果你直接将这些字符串写在 Dart 代码里,任何初级黑客都能通过反编译你的 HAP 包,轻松获取这些敏感资产,导致巨大的商业损失。 envied_generator 配合 envied 就是专门解决这一安全痛点的。它不仅能将配置从 .env 文件读取到代码中,更关键的是它支持 Obfuscate(代码混淆)。它将你的 Key 转化为一串复杂的位运算逻辑,让反编译后的结果变得面目全非,为鸿蒙应用的资产安全筑起第一道堤坝。 一、配置加固工作流模型 该库通过代码生成,将明文配置文件转化为混淆后的 Dart 类。 .env (敏感明文) envied_generator

By Ne0inhk