fst 共享后缀_FST源代码解读2——FST的生成

本篇博客介绍FST的生成。它使用的是生成器模式,因为FST的生成太复杂了,所以必须使用生成器模式,他的类是:org.apache.lucene.util.fst.Builder.Builder(INPUT_TYPE, int, int, boolean, boolean, int, Outputs, boolean, float, boolean, int),代码如下:

/**

inputType 表示的是输入的类型,FST规定只能输入数字类型,字符串的输入也要转化为数字,这里是判断字符串的范围,不同的INPUT_TYPE有不同的范围

minSuffixCount1:这个说的是穿越某个节点的边的数量的下限,如果小于这个值,则要删除这个节点,在lucene中是0,所以永远不会删除,不用管这个参数就可以。

minSuffixCount2:不用管这个参数,是0,在代码中不起作用

doShareSuffix:最后编译节点进入FST的时候,要不要共享后缀,

doShareNonSingletonNodes:当编译某一个节点的时候,如果这个节点是多个term都穿过的,是否要共享此节点,如果不共享,则直接编译入fst中,否则要放入一个去重的对象中,让其他的节点共享这个节点。

shareMaxTailLength:当编译进fst时要共享后缀的额时候,最多共享多少个

outputs:输出的类型

doPackFST:对最终生成的FST,要不要继续压缩(后面会专门将压缩的过程)

acceptableOverheadRatio:在使用packedInts的时候使用的参数(参见我描述packedInts的博客:https://www.iteye.com/blog/suichangkele-2427364 有多篇,不一一列出)

allowArrayArcs:在存储一个节点的多个发出的arc的时候,对于某一个arc的存储,是否可以使用fixedArray的格式,后面会有介绍

bytesPageBits:在使用BytesStore对象记录fst编译后的二进制内容时,使用的byte[]的大小

*/

public Builder(FST.INPUT_TYPE inputType, int minSuffixCount1, int minSuffixCount2, boolean doShareSuffix,

boolean doShareNonSingletonNodes, int shareMaxTailLength, Outputs outputs, boolean doPackFST,

float acceptableOverheadRatio, boolean allowArrayArcs, int bytesPageBits) {

this.minSuffixCount1 = minSuffixCount1;

this.minSuffixCount2 = minSuffixCount2;

this.doShareNonSingletonNodes = doShareNonSingletonNodes;

this.shareMaxTailLength = shareMaxTailLength;

this.doPackFST = doPackFST;

this.acceptableOverheadRatio = acceptableOverheadRatio;

this.allowArrayArcs = allowArrayArcs;

fst = new FST<>(inputType, outputs, doPackFST, acceptableOverheadRatio, bytesPageBits);//生成一个fst,

bytes = fst.bytes;

assert bytes != null;

if (doShareSuffix) {//这个就是共享后缀的部分,如果是的话,需要一个单独的对象,用来查找共享后缀,这个对象后面有介绍。

dedupHash = new NodeHash<>(fst, bytes.getReverseReader(false));

} else {

dedupHash = null;

}

NO_OUTPUT = outputs.getNoOutput();//对于没有输出的arc,统一通这个作为输出

@SuppressWarnings({"unchecked" })

final UnCompiledNode[] f = (UnCompiledNode[]) new UnCompiledNode[10];//frontier的数组

frontier = f;

for (int idx = 0; idx < frontier.length; idx++) {

frontier[idx] = new UnCompiledNode<>(this, idx);

}

}

上面提到了UnCompiledNode这个类,这个类就是构成Frontier的最小单位,在,用于表示没有编译进FST的节点类,看一下这个类:

/** 还没有写入FST的term的节点,保存一个出现的但是还没有写入FST的值
Expert: holds a pending (seen but not yet serialized) Node. */

public static final class UnCompiledNode implements Node {

final Builder owner;

/** 发出的arc边的数量,一个节点上可能有多个arc,如果是最后一个Node,则是0 */

public int numArcs;

/** 由这个节点出发的所有的arc */

public Arc[] arcs;

// TODO: instead of recording isFinal/output on the node, maybe we should use -1 arc to mean "end" (like we do when reading the FST). Would simplify much code here...

/** 节点的输出,有时候节点也是有输出的,就在下面的prependOutput方法中,其实就是以后的finalOutput,以后会有介绍 */

public T output;

/** 到这个节点截止是不是一个完整的term,如果这个节点是final的,则其可能含有output,后面会解释 */

public boolean isFinal;

/** 有多少个线路走过这个节点,无论是不是最后一个,都算是经过,第一个node的这个属性表示一共多少个term */

public long inputCount;

/** 节点在term中的偏移量(下标),第一个是不用的,是root
This node's depth, starting from the automaton root. */

public final int depth;

/** @param depth The node's depth starting from the automaton root. Needed for LUCENE-2934 (node expansion based on conditions other than the fanout size). */

@SuppressWarnings({"unchecked" })

public UnCompiledNode(Builder owner, int depth) {

this.owner = owner;

arcs = (Arc[]) new Arc[1];

arcs[0] = new Arc<>();

output = owner.NO_OUTPUT;

this.depth = depth;

}

@Override

public boolean isCompiled() {

return false;

}

/** 清除,当把这个节点编译进fst之后调用,因为他已经进入FST了,所以留着也没用了。 */

public void clear() {

numArcs = 0;

isFinal = false;

output = owner.NO_OUTPUT;

inputCount = 0;

// We don't clear the depth here because it never changes for nodes on the frontier (even when reused).

}

/** 获得最后添加的一个arc的输出值 */

public T getLastOutput(int labelToMatch) {

assert numArcs > 0;

assert arcs[numArcs - 1].label == labelToMatch;

return arcs[numArcs - 1].output;

}

/**

* 添加一个arc,到下一个节点,此时并没有添加输出,输出暂定为没有输出,并且设置为不是final

* @param labelarc上的值(不是输出)

* @param target 链接的下一个节点

*/

public void addArc(int label, Node target) {

assert label >= 0;

<
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值