

图2-前缀树-字典
不同结点有不同的地址值,不同边也有相对应的地址值,但是所有的接收状态结点即最终结点都指向同一地址。
一、搜索过程
以下默认编辑距离是2,以查询fr为例;
-
创建包含字典的数据结构 **ArrayList<String> myArrayList = **new ArrayList(Arrays.asList(new String[]{"ab", "cdf", "def","fri"})); **MDAG myMDAG =** new MDAG(myArrayList); 到此,字典就建成一棵前缀树了,如图2所示。 -
三种方式查询方式:
- 通过表格确定字典中距“树”的编辑距离2以内的所有字符串(理想的用例:编辑距离<= 2)
**LinkedList<String> ldNeighborsLinkedList = **LevenshteinAutomaton.tableFuzzySearch(2, "fr", myMDAG); //"fr", "fri"
- 通过动态编程确定字典中距“树”的编辑距离2以内的所有字符串(理想的用例:内存容量低,编辑距离> = 2)
**LinkedList<String> ldNeighborsLinkedList =** LevenshteinAutomaton.fuzzySearchNonAutomaton(2, "fr", myArrayList); //"fr", "fri" c.** 通过自动机遍历字典中与“树”的编辑距离为2的所有字符串** **LinkedList<String> ldNeighborsLinkedList = **LevenshteinAutomaton.iterativeFuzzySearch(2, "fr", myMDAG); //"fr", "fri" ?
方法内部的大体流程为:
- 依次遍历整体树,首先可以先遍历第一层得到“a,c,d,f”压栈,然后可以找到“fri”这一支;
- 之后,先遍历f 这一结点,然后通过State中的相关词函数-getRelevantSubwordCharacteristicVector(),找到待检查词“fri”的相关词,并返回AugBitSet格式的数据,数据里存储的是与“fri”相关词向量和相关词与检索向量之间的碰撞位置;(碰撞位置不太了解)
- 再则,通过State里的transition(),读取相关词向量、编辑距离等信息,之后,**transitionInternal()根据最大编辑距离、相关子字符串、碰撞位置信息等来为positon类内部设置的枚举类型赋值,从而procureTransition()**判断出可能的所有状态(相关词不定,正在处理的字符为f,可能的状态为插入、替换、删除),并把结果以数组的形式返回。之后,**execute()**根据目前的状态切换到下一个位置(改变I和E的值),接着处理下一个字符r,依次类推,直到正在处理的结点是接收状态结点,就结束,因为只要最后一个可以变换成目标。
- 最后,到其它支,发现“a,c,d”都不能在2个编辑距离之内转换成fri,因此进行剪枝策略。
?
?
?
二、再来了解几个重要类和函数:
1. State:Position数组是成员变量,此数组内部包含全部可能的转换情况,例如fri和f最比较可能是插入、删除;
函数:
2. getRelevantSubwordCharacteristicVector:根据相关词的公式,获取到与待检索词的相关词的长度
(相关词:在该长度内,在编辑距离的限制下,可准确的判断出该向量是否有可能转化成待检索词)
3. transition:调用position的内部方法,进行状态的转换
4. AugBitSet:Bitset的继承类,用来储存相关词向量和检索向量之间的碰撞位置,如f和frien则会产生(1,0,0,0,0)
5. Position:
成员:
I(目前正在处理的字符的位置,例如stand中的s为0、t为1) E(目前已经进行了多少次编辑) T(是否为可接受状态) 注:可近似对比为NFA图,I为横坐标、E为纵坐标
状态:
MATCH:匹配,eg: s,正在处理的字符串为s INSERTION:插入,eg: s,正在处理的字符串为s,结果为ss PRETRANSPOSITION TRANSPOSITION SUBSTITUTION:eg: 替换,s,正在处理的字符串为w,结果为w DELETION:删除,eg: ss,结果为s FAILURE:失败状态,后续的枝条将会被剪掉,成为剪枝
方法:
execute:根据目前的状态切换到下一个位置(改变I和E的值) procureTransition:根据内部设置的枚举类型,判断出可能的所有状态(st,正在处理的字符为t,可能的状态为插入、替换、删除),结果以数组的形式返回 transitionInternal:根据最大编辑距离、相关子字符串、碰撞位置信息等来为positon类内部设置的枚举类型赋值,从而使procureTransition方法可以调用 编辑距离相关函数:
- 确定两个单词之间的编辑距离
int editDistance **= **LevenshteinAutomaton.computeEditDistance("fri", "frien"); //1
- 确定两个字符串是否在彼此的给定编辑距离内
**boolean areLDNeighbors =** LevenshteinAutomaton.areWithinEditDistanceNonAutomaton(2, "fri", "frien"); //true ?
|