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