You need to enable JavaScript to run this app. 如何构建简易分词器:基于给定词典实现无空格语句分词
优惠活动
大模型
产品
解决方案
定价
更多

如何构建简易分词器:基于给定词典实现无空格语句分词

简易连续匹配分词器实现

核心需求

给定以列表形式存储的词典d、无间隔待处理语句s,输出切分后和词典匹配的连续分词单元(token),要求切分结果符合连续覆盖的规则,不输出零散的重叠匹配碎片。
对应测试场景:

  • 测试词典:["the","snow","ball","snowball","is","cold"]
  • 测试语句:"thesnowballisverycold"
  • 预期输出:["the","snowball","is","cold"]

现有实现的核心问题

当前写的递归subs函数,逻辑是枚举所有可由原文字符拼接形成的子序列,最后取枚举结果和词典的交集,这个实现存在两个本质偏差:

  1. 匹配范围不对:枚举的是任意字符顺序的组合子序列,不是原句中连续存在的字符串,大量非连续的拼接结果根本不属于有效分词范畴
  2. 没有位置约束:只要词典词条的字符在原句中按顺序出现过,不管和前后的切分段有没有位置重叠,都会被纳入结果。最后跑出来的["snow","ball","cold","is","snowball","the"]本质是把所有能在原句找到字符顺序匹配的词典词条堆在了一起,完全不是连续切分得到的token序列,自然不符合预期。

适配需求的简易实现方案

要达到预期效果,完全不需要做全量子串枚举,用最经典的最大正向匹配规则就能实现,逻辑极简、刚好覆盖当前场景:

  • 预处理阶段把词典转成集合方便快速查找,同时记录词典内最长词条的长度,减少匹配时的无效遍历
  • 从语句的起始位置开始,从最长可能的匹配长度往短逐次尝试,只要当前位置往后截取的连续子串能在词典中命中,就把这个词条作为一个分词单元,将指针移动到该词条的末尾位置,继续向下匹配
  • 遇到无法匹配的零散片段(比如例子中的very),直接将指针向后移动一位跳过,不纳入最终分词结果

可直接运行的示例代码:

# 初始化词典与待处理语句
dict_list = ["the","snow","ball","snowball","is","cold"]
sentence = "thesnowballisverycold"

# 词典预处理:转集合优化查找效率,记录最长词条长度
word_set = set(dict_list)
max_word_len = max(len(word) for word in dict_list)

tokens = []
pos = 0
while pos < len(sentence):
    matched_word = None
    # 从最长匹配长度开始逐次缩短尝试
    for current_len in range(min(max_word_len, len(sentence) - pos), 0, -1):
        sub_str = sentence[pos:pos + current_len]
        if sub_str in word_set:
            matched_word = sub_str
            break
    if matched_word:
        tokens.append(matched_word)
        pos += len(matched_word)
    else:
        # 无匹配的字符直接向后跳过
        pos += 1

print(tokens)

运行上述代码的输出和预期完全一致:

['the', 'snowball', 'is', 'cold']

这个实现通过最长匹配优先的规则,天然会过滤掉短的重叠匹配(比如snow、ball),优先选更长的有效词条(比如snowball),完全符合对简易分词器的需求,没有引入额外的复杂依赖。


内容的提问来源于stack exchange,提问作者Ron

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.06 17:06:10