学习笔记——搞懂FST数据结构

本文深入解析了FST(Finite State Transducer)数据结构,介绍了其查询过程、Lucene源码中的实现细节,包括Builder类和BlockTreeTermsWriter,以及FST在存储(TermIndex和TermDictionary)和构建过程中的关键概念。通过图解展示了节点添加和FST字符串读取的步骤。

目录

数据结构FST简述

FST简述及它的查询过程

从Lucence源码中看FST的结构

查看builder类(package org.apache.lucene.util.fst)

查看BlockTreeTermsWriter类(packageorg.apache.lucene.codecs.blocktree)

FST存储到文件中的存储结构(TermIndex词项索引和TermDictionary词项字典)

FST构建(读取和写入数据)

通过图解一步步搞清楚结点的添加过程。

读取FST的字符串.


首先声明图片数据来源:b站马士兵教育。

luncence源码百度云:

链接:https://pan.baidu.com/s/12EQtJ_t-P3-P_CJnHIfnEw 
提取码:abcd

数据结构FST简述

了解一下trie前缀树:复用所有前缀



FSM(Finite State Machines)有限状态机: 表示有限个状态集合以及这些状态之间转移和动作的数学模型。其中一个状态被标记为开始状态,0个或更多的状态被标记为final状态

FSA:有限状态接收机


确定性:在任何给定状态下,对于任何输入,最多只能遍历一个transtion
非循环:不可能重复遍历同一个状态
Final唯一性:当且仅当有限状态机在输入序列的末尾处于最终状态时,才接受特定的输入序列
以上例子,如果输入‘wl’会怎样?其实就是可以搜索到的了。因为l指向的节点3已经是final节点了。为解决这样的问题,引出FST

FST简述及它的查询过程

FST:有限状态转化机
FST最重要的功能是可以实现key到value的映射,相当于HashMap<K,V>。FST的查询速度比hashMap慢一点,但是内存消耗比hashMap小很多。FST在lucene大量使用:倒排索引的存储,同义词词典的存储,搜索关键字建议等等。
对于es来说,它是基于lucence开发,底层的数据结构使用的就是fst,它的主要优点:

  1. 查询快
  2. 极致压缩空间占用
    特性:
    确定性:在任何给定状态下,对于任何输入,最多只能遍历一个transtion
    非循环:不可能重复遍历同一个状态
    transducer: 转化器有相关的值(payload),final节点会输出一个值
    比起前面的前缀树以及FSA,在存储的时候多了一个value值。
    考虑以下输入字符:







    此时,再输入wl试试?尽管节点3是final节点,但是由于值对不上,所以不会搜索成功的。

从Lucence源码中看FST的结构

查看builder类(package org.apache.lucene.util.fst)



节点模型:node

考虑需要输入这样一组数据

由于按照字典序排序,输入abd的时候,由于此时系统不知道后面是否还存在abde,abdc类似的数据,所以此时输入的abd就是unCompliledNode

当输入abe的时候,已经可以确定后面不会有abd这些数据了(字典序),但是无法确定ab前缀还是否存在,直到输入ac为止才确认不会有ab前缀了。此时字符’d’被移除出frontier数组,把它冻结起来 -freezeTail
 

描述边,也就是出度的类是Arc


label:存放那个输入的字符作为Key
output:存放对应的值也就是Value
target:简单理解为存放偏移量,如果arc描述的字符不是最后一个字符的时候,就会有这么一个偏移量。
flags:其实就是起始值,通过位运算(通用最小化算法)得来.


查看BlockTreeTermsWriter类(packageorg.apache.lucene.codecs.blocktree)

PendingEntry—PendingBlock --PendingTerm
通过输入的字符,一般的是Term,满足某种条件则会被聚合成Block



Block——根据给的阈值(min24,max48)划分成Block或者Term
简单理解:若是子节点少于24,则仍然为单独的PedingTerm,若是大于等于24,则会被聚合成一个PendingBlock.如果这个PendingBlock大于48,则会被分成多个FloorBlock

通过构建过程来理解:
1.输入abd,abe,此时还都是正常的情况。(abd和abe都是term)

2.输入abfi,abfj,abfk,此时可以看到f已经有三个出度k I j了,初步满足聚合成Block的条件

此时还都是term,没有聚合成block,虽然已经满足了条件给出的3个。但是由于输入项还没确定完.所以还不能聚合起来。

3输入abgl---->聚合成Block
由于此时已经确定f已经不会做修改了,此时由于f有三个出度,所以I j k可以聚合成pedingBlock


4.继续输入abgm,abgn,abgo,abgp,abgp,abgq,abgr。此时g已经有七个出度了!!但是没有聚合成Block


等到结束g出度的输入的时候,才会发生聚合block
5.输入abh,此时聚合成g的block,它底下还有两个floorblock
 

FST存储到文件中的存储结构(TermIndex词项索引和TermDictionary词项字典)

.tip: 存放Term-Index

.tim:存放Term-Dictonary

Term-index里面存放的FSTindex存放Block的前缀记录,末尾指向block..这些block具体存放在.tim文件也就是term Dictonary里面。

block具体存放的是啥?

 

BlockHeader:

Suffix:

states:

metaLength:

再来看看FST-Index和block更详细的内容

 

以这样一个词项字典

还是这张图

构建FST-Index

其中flag是标志位,代表着一个block的开始.

### FST(有限状态转换器)的定义 FST(Finite State Transducer)是一种有限状态自动机,它不仅能够识别输入字符串,还能将输入字符串转换为输出字符串。FST由一组状态、输入符号集、输出符号集、转移函数和初始状态组成。每个状态转移不仅考虑输入符号,还产生一个输出符号。这种特性使得FST非常适合用于需要输入输出映射的应用场景[^3]。 ### FST的工作原理 FST的核心原理是通过状态转移来处理输入序列并生成相应的输出序列。每个状态转移规则定义了在给定输入符号的情况下,如何从一个状态转移到另一个状态,并且生成一个输出符号。FST可以被视为一种扩展的有限状态自动机,其中每个转移不仅有一个输入标签,还有一个输出标签。这种结构允许FST在处理输入的同时生成输出,从而实现复杂的转换功能。 在实际应用中,FST通常用于处理文本数据,例如在自然语言处理中进行词形变化、拼写检查、机器翻译等任务。FST的强大之处在于它可以高效地处理大量的输入输出映射关系,并且能够在内存中紧凑地存储这些映射关系[^1]。 ### FST的使用场景 1. **信息检索**:FST被广泛应用于搜索引擎中,用于构建词典(Term Dictionary),支持高效的前缀查询、范围查询等操作。例如,Lucene使用FST来存储索引中的术语,从而提高查询效率[^2]。 2. **自然语言处理**:在NLP领域,FST用于处理复杂的文法规则,如词形变化、拼写检查、语音识别等。FST能够高效地处理这些任务,因为它可以通过有限状态自动机来表示和处理文法规则[^3]。 3. **机器翻译**:FST可以用于构建翻译模型,将一种语言的句子转换为另一种语言的句子。这种方法在早期的机器翻译系统中得到了广泛应用[^3]。 4. **数据压缩**:FST可以用于数据压缩算法中,通过将重复的模式映射到更短的表示形式,从而减少存储空间和传输成本。 5. **生物信息学**:在生物信息学中,FST用于处理DNA序列、蛋白质序列等生物数据,支持高效的序列比对和模式识别[^3]。 ### 示例代码 以下是一个使用Lucene库构建FST的简单示例: ```java import org.apache.lucene.util.fst.*; import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.IntsRef; public class FSTExample { public static void main(String[] args) throws Exception { String inputValues[] = {"cat", "deep", "do", "dog", "dogs"}; long outputValues[] = {5, 7, 17, 18, 21};
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值