指令前缀既能结束又能继续时怎样组织提示:机制演算第12例
自动补全中,一个前缀可能已经是一条完整指令,同时还通向更长的指令。若只把叶子当成完整项,就会漏掉这种两种身份同时存在的节点。
将每条指令逐字符放入前缀树,完整指令在结束节点记录自身使用次数。查询前缀后,分别列出它是否完整、下一层可选字符,以及所有后代完整指令中使用次数最高的三项,同次数按字母顺序。
本例的输入和输出
完整指令及使用次数为{'GIVE': 1, 'GO': 15, 'LEAVE': 4, 'LOAD': 11, 'LOOK': 5, 'LOOP': 12, 'MAP': 10, 'MARK': 20, 'MOVE': 17, 'PICK': 15, 'PING': 19, 'PLAY': 13, 'PORT': 15, 'SAVE': 20, 'SEND': 13, 'SET': 13}。没有记录的指令不属于当前集合。
查询前缀 | 路径存在 | 自身完整指令次数 | 下一字符 | 前三项 空前缀 | True | 0 | ['G', 'L', 'M', 'P', 'S'] | [['MARK', 20], ['SAVE', 20], ['PING', 19]] G | True | 0 | ['I', 'O'] | [['GO', 15], ['GIVE', 1]] GO | True | 15 | [] | [['GO', 15]] LO | True | 0 | ['A', 'O'] | [['LOOP', 12], ['LOAD', 11], ['LOOK', 5]] P | True | 0 | ['I', 'L', 'O'] | [['PING', 19], ['PICK', 15], ['PORT', 15]] S | True | 0 | ['A', 'E'] | [['SAVE', 20], ['SEND', 13], ['SET', 13]] SET | True | 13 | [] | [['SET', 13]] SE | True | 0 | ['N', 'T'] | [['SEND', 13], ['SET', 13]] MZ | False | 0 | [] | [] LE | True | 0 | ['A'] | [['LEAVE', 4]]
表格中的编号只标识当前例子的元素,不应把对象身份、数组下标与计算数值混为一谈。阅读时先核对输入和边界,再沿记录检查每一步;空结果表示规则下没有可用项,并不是默认返回数值零。
复核与适用条件
节点没有孩子不等于查询失败,节点有孩子也不等于它不能结束。前缀为空时查询整个指令集;前缀不存在时返回空结果。使用次数只属于完整指令,不能混成经过该节点的总次数。
本例只使用大写英文字符,未处理大小写折叠、拼写纠错或多语言文字。提示排序是本文规定的频次优先模型,不代表最近使用或最适合当前场景,实际界面还应结合自身的可用指令范围。
练习时先独立复算一小段,再检查整体结果是否满足文中条件。遇到差异应保留中间记录并定位第一处不一致,而不是只调整最后答案。更换输入或操作规则后,需要重新计算,原记录只对这一例负责。
