自然语言处理学习笔记(七)————字典树效率改进

news2024/11/25 12:57:00

目录

1. 首字散列其余二分的字典树

2.双数组字典树

3.AC自动机(多模式匹配)

(1)goto表

(2)output表

(3)fail表

4.基于双数组字典树的AC自动机


        字典树的数据结构在以上的切分算法中已经很快了,但还有一些基于字典树的算法改进,把分词速度推向了千万字每秒的级别,主要按照以下递进关系优化:

  • 首字散列其余二分的字典树
  • 双数组字典树
  • AC自动机(多模式匹配)
  • 基于双数组字典树的AC自动机

1. 首字散列其余二分的字典树

        散列函数用来将对象转换为整数。散列函数必须满足的基本要求是:对象相同,散列值必须相同。散列函数设计不当,则散列表的内存效率和查找效率都不高。Python没有char类型,字符被视作长度为1的字符串,所以实际调用的就是str的散列函数。在64位系统上,str的散列函数返回64位的整数。但Unicode字符总共也才136690个,远远小于2^64。这导致两个字符在字符集中明明相邻,然而散列值却相差万里。

        Java中的字符散列函数则要友好一些,Java中字符的编码为UTF-16。每个字符都可以映射为16位不重复的连续整数,恰好是完美散列。这个完美的散列函数输出的是区间[0,65535]内的正整数,用来索引子节点非常合适。具体做法是创建一个长为65536的数组,将子节点按对应的字符整型值作为下标放入该数组中即可。这样每次状态转移时,只需访问对应下标就行了,这在任何编程语言中都是极快的。然而这种待遇无法让每个节点都享受,如果词典中的词语最长为l,则最坏情况下字典树第l层的数组容量之和为O(65536^l)。内存指数膨胀,不现实。一个变通的方法是仅在根节点实施散列策略。

        字典树其实就是一棵前缀树(指的是前缀相同的词语必然经过同一个节点) 如何加速呢?在扫描"自然语言处理"这句话的时候,朴素实现会依次查询"自"、"自然"、"自然语"、"自然语言"等词语是否在词典中。但事实上,如果"自然"这条路径不存在于前缀树中,则可以断定一切以"自然"开头的词语都不可能存在。

2.双数组字典树

        状态转移复杂度为常数的数据结构。它由basecheck两个数组构成,又简称双数组

3.AC自动机(多模式匹配)

        我们已经知道,字典树的本质就是DFA,假设每次状态转移的时间复杂度为常数。那么对文本“123”的扫描一共发生了六次状态转移:1、12、123;2、23;3.对于文本长度为n来说,共发生了 O(n^2) 次状态转移,所以复杂度为  O(n^2) 

        那么可不可以只进行一次扫描就查询出所有出现的单词呢,AC自动机就可以做到,它是一种  O(n) 复杂度的算法。给定多个词语(模式串, pattern),从母文本中匹配他们的问题称为多模式匹配。在中文处理中,汉字就是常见的短模式串,AC自动机在中文自然语言处理中应用更广泛。

        举个例子:我们的模式串为“自然语言”,如果用字典树查询,以“自“为起点, 找到”自然语言“后,起点又退回到”然“继续扫描...如果扫描到”自然语言“的同时知道”然语言“、”语言“、”言”不在字典树中,则可以少查询三次,观察这三个字符串,它们共享递进式的后缀,所以可以引入后缀树。AC自动机在前缀树的基础上为每个节点建立后缀树,节省大量查询。

AC自动机由goto表,fail表和output表组成,分别类似于前缀树和后缀树。

(1)goto表

        goto表也叫success表,其实就是一颗前缀树,用来将每个模式串索引到前缀树上。下面引用经典的ushers作为母文本,模式串集合为{he,she,his,hers}

        它的构建与前缀树一致,唯一不同的是,根节点不光可以按h和s转移,还接受任意其他字符,转移终点都是自己。这样形成了一个圈,使得一棵树变为一幅有向有环图。这个圈的目的在于,扫描时若遇到非h且非s的字符,状态机一直保持初始状态。

(2)output表

         给定一个状态,我们需要知道该状态是否对应某个或某些模式串,以决定是否输出模式串以及对应的值。这时用到的关联结构被称为utput 表。在图2-9所示的例子中,output表中的状态就是图中的深蓝色节点,对应的output 如表所示。

         output 表中的元素有两种,一种是从初始状态到当前状态的路径本身对应的模式串(比如2号状态),另一种是路径的后缀所对应的模式串(比如5号状态)。于是它的构造也分为两步,第一步与字典树类似,就是记录完整路径对应的模式串。第二步则是找出所有路径后缀及其模式串,这一步可以与fai1表的构造同步进行。

        为goto表加上output表

(3)fail表

        fail表保存的是状态间一对一的关系,存储状态转移失败后应当回退的最佳状态。最佳状态指的是能记住已匹配上的字符串的最长后缀的那个状态。比如,匹配she后来到状态5,再来一个字符,goto失败,哪个状态才是fail的最佳选择呢?当前匹配到的字符串为she,最长后缀为he,对应路径0-1-2。因此,状态2就是状态5 fail的最佳选择。fail到状态2之后,自动机记住了he,做好了接受r的准备。再比如,匹配his后来到状态7,再来一个字符,goto失败了。his 的最长后缀为is,可惜没有这条路径;次长后缀为s,对应路径0-3,因此状态7应当fail到3。
        如何构建fail表?定义s为当前状态;S.goto(c)为转移表,返回s按字符c转移后的状态,null表示转移失败;S.fail为fail表,代表转移失败时从状态S回退的状态。fail表的构建方法如下。
      (1)初始状态的goto表是满的,永远不会失败,因此没有fail指针。与初始状态直接相连的所有状态,其fail指针都指向初始状态,如图中的虚线所示。

         (2)从初始状态开始进行广度优先遍历(BFS),若当前状态S接受字符c直达的状态为T,则沿着S的fail指针回溯,直到找到第一个前驱状态F,使得F.goto(c) != null。将T的fail指针设F.goto(c),也即:

F = S.fail
while F.goto(c) == null
    F= F.fail
T.fail = F.goto(c)

       (3)由于F路径是T路径的后缀,也就是说T一定包含F,因而T的output 也应包含F的output。于是更新:

T.output += F.output

        为上图加上完整的fail表后,自动机如图所示。

        算上fail表的虚线,从后往前看,AC自动机由许多后缀树构成。其中一棵如图所示。

         字典树状态转移可能失败,失败时扫描起点往右挪一下,重新扫描。而在AC自动机中,按goto表转移失败时就按fail转移,永远不会失败,因此只需扫描一遍文本。

4.基于双数组字典树的AC自动机

        双数组字典树能在O(1)(1是模式串长度)时间内高速完成单串匹配,并且内存消耗可控,然而软肋在于多模式匹配。如果要匹配多个模式串,必须先实现前缀查询,然后频繁截取文本后缀才可多匹配。比如 ushers、shers、hers…这样一份文本要回退扫描多遍,性能较低。既然 AC 自动机的goto表本身就是一棵字典树,能否利用双数组字典树来实现它呢?如果能用双数组字典树表达 AC自动机,就能集合两者的优点,得到一种近乎完美的数据结构。
        ACDAT的基本原理是替换 AC自动机的goto表,也可看作为一棵双数组字典树的每个状态(下标)附上额外的信息。上节提到,AC自动机的goto表就是字典树,只不过AC自动机比字典树多了output 表和fail表。那么ACDAT的构建原理就是为每个状态(base[i]和check[i])构建output[i][]和fail[i]。具体说来,分为3步。
(1)构建一棵普通的字典树,让终止节点记住对应模式串的字典序。
(2)构建双数组字典树,在将每个状态映射到双数组时,让它记住自己在双数组中的下标。
  (3)构建AC自动机,此时fail表中存储的就是状态的下标。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

探索未知世界:桌面端3D GIS引领地理信息新时代

近年来,桌面端的三维地理信息系统(3D GIS)在地理信息领域迎来了显著的发展,为我们带来了更深入、更丰富的地理空间认知和数据分析体验。从城市规划到环境保护,从资源管理到应急响应,桌面端的3D GIS正逐渐成…

ICC2 update tech file / update ndm

拾陆楼知识星球入口 update tech file read_tech_file new_tf save_lib update ndm set_ref_libs -ref_libs $new_ref_list -library xx.lib save_lib rebind_block

四信5G工业路由器赋能5G LAN全连接工厂建设

5G作为“新基建”之首,肩负着驱动国民经济转型升级、促进实体经济与数字经济深度融合、满足各行各业高质量通信服务需求的重任。 随着5G技术的更新迭代,各行各业对网络的可靠性,确定性等提出更高的需求,5G LAN作为3GPP R16标准定…

视频监控/视频集中存储/云存储平台AI智能分析网关V3——功能简介

安防监控/视频集中存储/云存储平台AI智能分析网关V3内置了20多种AI算法,可针对安全生产、通用园区、智慧食安、石油化工等场景,提供基于视频智能检测技术的个性化行业解决方案。今天来具体介绍下v3版本的智能分析网关有哪些算法功能配置。 一、硬件 安防…

031 - 浮点类型(近似值 FLOAT,DOUBLE)

-FLOAT,DOUBLE: FLOAT和DOUBLE类型代表近似数字数据值。MySQL将四个字节用于单精度值,并将八个字节用于双精度值。 对于FLOAT,SQL标准允许对FLOAT括号中的关键字后面的位以精度(而不是指数的范围)进行可选规…

MyBatis实现分页功能及MyBatis的特殊符号---超详细介绍

一,分页的概念 分页是一种将大量数据或内容分割成多个页面以便逐页显示的方式。在分页中,数据被分割成一定数量的页,每页显示一部分数据或内容,用户可以通过翻页或跳分页是一种将大量数据或内容分割成多个页面以便逐页显示的方式。…

AI 浪潮下,W3AI 如何增强和激励 Web3 玩家研究和决策力?

更加个性化的 AI 服务是怎样的?近年来,不少主打 AI 服务的 Web3 初创项目开始兴起,凭借语音、文字、图像等全方位的用户数据跟踪和使用习惯定义,场景化的 AI Web3 产品开始围绕用户的工作、生活日常提供智能服务。这其中&#xff…

在router中使用pinia、在组件外使用pinia时 报错没有激活pinia

getActivePinia was called with no active Pinia. Did you forget to install pinia? 我想在路由守卫中使用store中部的数据,但是拿不到仓库,提示pinia没激活 解决方案:借鉴vben-admin 在每个模块中都把pinia和当前的仓库绑定一份暴漏出去…

微服务(rpc)

微服务(rpc) 微服务必备的模块生产者消费者管理平台流量控制集群情况下如何做到流量监控 负载均衡服务发现和治理序列化传输序列化和反序列化 微服务是一种架构风格,将一个应用程序拆分为一组小型、独立的服务,每个服务都可以独立…

Linux: 使用scp命令复制文件夹报 not a regular file 错误解决

使用scp 命令复制文件夹报 not a regular file 错误解决 解决办法: 加入参数 -r: 递归复制整个目录 scp命令参数详解

【MyBatis】:PageHelper分页插件与特殊字符处理

目录 一、PageHelper介绍 二、PageHelper使用 1. 导入pom依赖 2. Mybatis.cfg.xml 配置拦截器 3. 配置 Mapper.xml 4. 编写测试 三、特殊字符处理 1. 使用转义字符 2. 使用CDATA 区段 一、PageHelper介绍 PageHelper 是 Mybatis 的一个插件,这里就不扯了&a…

Unity——DOTween插件使用方法简介

缓动动画既是一种编程技术,也是一种动画的设计思路。从设计角度来看,可以有以下描述 事先设计很多基本的动画样式,如移动、缩放、旋转、变色和弹跳等。但这些动画都以抽象方式表示,一般封装为程序函数动画的参数可以在使用时指定&…

JUC初识

JUC 是什么 java.util.concurrent 在并发编程中使用的工具包 从线程start 开始 package com.jhj.Thread;public class ThreadDemo {public static void main(String[] args) {Thread t1 new Thread(() -> {}, "t1");t1.start();} }start 方法调的是native sta…

java:Tomcat

文章目录 背景服务器web 服务器服务资源的分类服务器软件的分类nginx 和 tomact总结 安装Tomcatbrew安装官网压缩包安装IDEA集成IDEA插件 说明 背景 在讲 Tomcat 是啥之前,我们先来了解一些概念。 服务器 可以理解为一个高性能的电脑,但是这个电脑现在…

Qt6和Rust结合构建桌面应用

桌面应用程序是原生的、快速的、安全的,并提供Web应用程序无法比拟的体验。 Rust 是一种低级静态类型多范式编程语言,专注于安全性和性能,解决了 C/C 长期以来一直在努力解决的问题,例如内存错误和构建并发程序。 在桌面应用程序开…

如何给开源仓库提交pull request?

Pull Request(PR)是一种在基于版本控制系统的协作开发中使用的功能,它允许开发人员将自己所做的代码更改(commits)提交给项目的主要代码库。具体而言,当在分支中做出代码更新后,开发人员可以发起…

射频有源器件的动态范围和交越失真

射频有源器件的动态范围和交越失真 1、增益压缩 一个输入信号Vin经过一个非线性网络后输出为Vout,Vout与Vin用泰勒级数的关系表示: Vout a0 a1*Vin a2*Vin^2 a3*Vin^3 …… a0为直流输出,a1为线性输出,a2为平方输出&…

Android 基础知识

一、Activity 1、onSaveInstanceState(),onRestoreInstanceState的调用时机 onSaveInstanceState 调用时机 从最近应用中选择运行其他程序时 但用户按下Home键时 屏幕方向切换时 按下电源案件时 从当前activity启动一个新的activity时 onRestorInstanceState调用时机 只…

windows下安装go环境 和vscode中go扩展

1. 首先安装GO Go下载地址:go.dev 选择相对应的版本,下载,运行安装程序,并打开命令提示符,运行 go env ,确认已经安装go 注意关注其中GOPATH和GOROOT,这两个地址可以在系统环境变量中进行设置…

在其他python环境中使用jupyter notebook

1、切换到目标python环境 activate 目标python环境 2、安装notebook内核包 pip install ipykernel 3、加环境加入到notebook中 python -m ipykernel install 目标python环境 4、切换到base环境 activate base 5、打开目标项目的对应盘 如果,项目在c盘&…