基于规则的分词

news/2025/3/6 17:43:24/

基于规则的分词

基于规则或词典的分词方法是一种较为机械的分词方法,其基本思想如下。

  • 将待分词语句中的字符串和词典逐个匹配。
  • 找到匹配的字符串则切分,不匹配则减去边缘的某些字符。
  • 从头再次匹配,直至匹配完毕或者没有找到词典的字符串而结束。

基于规则分词主要方法如下。

  • 正向最大匹配法(Maximum Match Method,MM法)。
  • 逆向最大匹配法(Reverse Maximum Match Method,RMM法)。
  • 双向最大匹配法(Bi-direction Matching Method,BMM法)。
python">def precompute_max_length(dictionary):"""计算词典中最大长度词的长度:param dictionary: 词典:return: 词典中最大长度词的长度"""return max(len(word) for word in dictionary) if dictionary else 0def forward_segmentation(text, dictionary):"""正向最大匹配:param text: 文本字符串:param dictionary: 词典:return: 将文本字符串中切词后的数组"""result = []i = 0max_len = precompute_max_length(dictionary)while i < len(text):found_word = ''# 尝试最长可能的词长max_possible = min(max_len, len(text) - i)for l in range(max_possible, 0, -1):candidate = text[i:i + l]if candidate in dictionary:found_word = candidatebreakif found_word:result.append(found_word)i += len(found_word)else:# 没有找到任何词,添加单个字符作为词汇result.append(text[i])i += 1return resultdef backward_segmentation(text, dictionary):"""逆向最大匹配:param text: 文本字符串:param dictionary: 词典:return: 将文本字符串中切词后的数组"""result = []i = len(text)max_len = precompute_max_length(dictionary)while i > 0:found_word = ''# 尝试最长可能的词长,从i处往回找max_possible = min(max_len, i)for l in range(max_possible, 0, -1):candidate = text[i - l:i]if candidate in dictionary:found_word = candidatebreakif found_word:result.insert(0, found_word)i -= len(found_word)else:# 没有找到任何词,添加最后一个字符作为词汇result.insert(0, text[i - 1])i -= 1return resultdef bidirectional_segmentation(text, dictionary):"""
双向最大匹配
:param text: 文本字符串
:param dictionary: 词典
:return: 将文本字符串中切词后的数组
"""result = []i = 0n = len(text)max_len = precompute_max_length(dictionary)while i < n:# 正向扫描查找词forward_word = ''max_possible_forward = min(max_len, n - i)for l in range(max_possible_forward, 0, -1):candidate = text[i:i + l]if candidate in dictionary:forward_word = candidatebreak# 反向扫描查找词backward_word = ''max_possible_backward = min(max_len, i)for l in range(max_possible_backward, 0, -1):candidate = text[i - l:i]if candidate in dictionary:backward_word = candidatebreak# 判断选择哪个词,如果长度相同则优先正向词?if len(forward_word) >= len(backward_word):result.append(forward_word)i += len(forward_word)else:result.append(backward_word)i -= len(backward_word)return result# 定义词典
word_set = {"中", "华", "民", "共和", "国", "人民", "共和国"}# 定义文本字符串
text = "中华人民共和国"# 正向分词
forward_result = forward_segmentation(text, word_set)
print("正向分词结果:", forward_result)# 逆向分词
backward_result = backward_segmentation(text, word_set)
print("逆向分词结果:", backward_result)# 双向分词
bidirectional_result = bidirectional_segmentation(text, word_set)
print("双向分词结果:", bidirectional_result)
正向分词结果: ['中', '华', '人民', '共和国']
逆向分词结果: ['中', '华', '人民', '共和国']
双向分词结果: ['中', '华', '人民', '共和国']

以下是代码的详细注释,解释了每个函数的功能和实现逻辑:

  1. precompute_max_length(dictionary)
    计算词典中最长单词的长度。
    如果词典为空,则返回0。
python">def precompute_max_length(dictionary):# 如果词典不为空,返回词典中最长单词的长度return max(len(word) for word in dictionary) if dictionary else 0
  1. forward_segmentation(text, dictionary)
    正向最大匹配分词算法。
    从左到右扫描文本,每次尝试匹配最长的单词。
python">def forward_segmentation(text, dictionary):result = []  # 存储分词结果i = 0  # 当前扫描位置max_len = precompute_max_length(dictionary)  # 获取词典中最长单词的长度while i < len(text):  # 遍历文本found_word = ''  # 用于存储找到的单词# 计算当前扫描位置的最大可能匹配长度max_possible = min(max_len, len(text) - i)for l in range(max_possible, 0, -1):  # 从最大可能长度开始递减candidate = text[i:i+l]  # 提取当前候选单词if candidate in dictionary:  # 如果候选单词在词典中found_word = candidate  # 找到匹配单词breakif found_word:  # 如果找到匹配单词result.append(found_word)  # 将单词加入结果i += len(found_word)  # 更新扫描位置else:  # 如果没有找到匹配单词result.append(text[i])  # 将当前字符作为单字加入结果i += 1  # 更新扫描位置return result  # 返回分词结果
  1. backward_segmentation(text, dictionary)
    逆向最大匹配分词算法。
    从右到左扫描文本,每次尝试匹配最长的单词。
python">def backward_segmentation(text, dictionary):result = []  # 存储分词结果i = len(text)  # 当前扫描位置(从文本末尾开始)max_len = precompute_max_length(dictionary)  # 获取词典中最长单词的长度while i > 0:  # 遍历文本found_word = ''  # 用于存储找到的单词# 计算当前扫描位置的最大可能匹配长度max_possible = min(max_len, i)for l in range(max_possible, 0, -1):  # 从最大可能长度开始递减candidate = text[i-l:i]  # 提取当前候选单词if candidate in dictionary:  # 如果候选单词在词典中found_word = candidate  # 找到匹配单词breakif found_word:  # 如果找到匹配单词result.insert(0, found_word)  # 将单词插入结果列表的开头i -= len(found_word)  # 更新扫描位置else:  # 如果没有找到匹配单词result.insert(0, text[i-1])  # 将当前字符作为单字插入结果列表的开头i -= 1  # 更新扫描位置return result  # 返回分词结果
  1. bidirectional_segmentation(text, dictionary)
    双向最大匹配分词算法。
    结合正向和逆向最大匹配算法,选择匹配长度更长的单词。
python">def bidirectional_segmentation(text, dictionary):result = []  # 存储分词结果i = 0  # 当前扫描位置n = len(text)  # 文本长度max_len = precompute_max_length(dictionary)  # 获取词典中最长单词的长度while i < n:  # 遍历文本# 正向扫描查找词forward_word = ''  # 存储正向匹配的单词max_possible_forward = min(max_len, n - i)  # 计算正向扫描的最大可能匹配长度for l in range(max_possible_forward, 0, -1):  # 从最大可能长度开始递减candidate = text[i:i+l]  # 提取当前候选单词if candidate in dictionary:  # 如果候选单词在词典中forward_word = candidate  # 找到匹配单词break# 反向扫描查找词backward_word = ''  # 存储逆向匹配的单词max_possible_backward = min(max_len, i)  # 计算逆向扫描的最大可能匹配长度for l in range(max_possible_backward, 0, -1):  # 从最大可能长度开始递减candidate = text[i-l:i]  # 提取当前候选单词if candidate in dictionary:  # 如果候选单词在词典中backward_word = candidate  # 找到匹配单词break# 判断选择哪个词if len(forward_word) >= len(backward_word):  # 如果正向匹配的单词长度大于等于逆向匹配的单词result.append(forward_word)  # 选择正向匹配的单词i += len(forward_word)  # 更新扫描位置else:  # 否则选择逆向匹配的单词result.append(backward_word)  # 选择逆向匹配的单词i -= len(backward_word)  # 更新扫描位置return result  # 返回分词结果

总结

  • precompute_max_length:计算词典中最长单词的长度,用于优化分词过程中的最大匹配长度。

  • forward_segmentation:正向最大匹配分词算法,从左到右扫描文本,优先匹配最长的单词。

  • backward_segmentation:逆向最大匹配分词算法,从右到左扫描文本,优先匹配最长的单词。

  • bidirectional_segmentation:双向最大匹配分词算法,结合正向和逆向匹配,选择匹配长度更长的单词,以提高分词的准确性。


http://www.ppmy.cn/news/1577126.html

相关文章

FastGPT 源码:controller.ts 主要定义

文章目录 FastGPT 源码&#xff1a;controller.ts 主要定义1. 主要函数和参数定义2. 参数初始化3. 内部工具函数4. 多查询召回实现5. 主流程执行 FastGPT 源码&#xff1a;controller.ts 主要定义 controller.ts 中的核心搜索实现。 1. 主要函数和参数定义 type SearchDatas…

【Nest】中间件

一、中间件的创建与使用 1. 类中间件 通过实现 NestMiddleware 接口创建类中间件&#xff0c;需定义 use 方法&#xff1a; import { Injectable, NestMiddleware } from nestjs/common; import { Request, Response, NextFunction } from express;Injectable() export clas…

QDBus:Qt对DBus的封装支持

QDBus&#xff1a;Qt对DBus的封装支持 引言 在Qt应用程序开发中&#xff0c;进程间通信&#xff08;IPC&#xff09;是实现模块化、服务化和分布式架构的关键技术。QDBus是Qt框架对DBus&#xff08;Desktop Bus&#xff09;协议的封装&#xff0c;为开发者提供了一种高效、便捷…

The Rust Programming Language 学习 (二)

通用编程概念 变量和可变性 默认情况下变量是不可变的&#xff08;immutable&#xff09;,不过你也可以选择让变量是可变的&#xff08;mutable&#xff09;. 变量的遮蔽 你可以声明和前面变量具有相同名称的新变量,说这个是第一个变量被第二个变量遮蔽&#xff08;shadow&…

Java TCP 通信:实现简单的 Echo 服务器与客户端

TCP&#xff08;Transmission Control Protocol&#xff09;是一种面向连接的、可靠的传输层协议。与 UDP 不同&#xff0c;TCP 保证了数据的顺序、可靠性和完整性&#xff0c;适用于需要可靠传输的应用场景&#xff0c;如文件传输、网页浏览等。本文将基于 Java 实现一个简单的…

【GB28181】 SIP信令服务器

概述 本文仅总结关于GB28181下的注册、心跳维持等与推流拉流相配合的SIP信令&#xff0c;主要基于eXosip库实现&#xff1b;其中搭建信令服务器参考了开源代码以及B站up北小菜&#xff0c;文章结尾有链接 主要逻辑梳理 配置自身SIP服务器&#xff0c;同时配置自己想要访问的SI…

6.从零开始学会Vue--{{路由}}

1.路由简介 Vue 作为一个渐进式框架&#xff0c;在使用 vue-router 之后可以是程序变为一个 SPA 的单页面应用, 它的本质是使用了 js 的 History API&#xff1a; Vue Router 利用浏览器的 History API&#xff08;如 pushState 和 replaceState&#xff09;&#xff0c;实现…

自学微信小程序的第八天

DAY8 1、使用动画API即可完成动画效果的制作,先通过wx.createAnimation()方法获取Animation实例,然后调用Animation实例的方法实现动画效果。 表40:wx.createAnimation()方法的常用选项 选项 类型 说明 duration number 动画持续时间,单位为毫秒,默认值为400毫秒 timing…