当前位置: 首页 > 后端技术 > PHP

字典树的实现和介绍

时间:2023-03-29 19:22:25 PHP

字典树的实现与介绍在优化旧代码时,会用到字典树。我用Java写了一个字典树。分享。先说一下常见的引用场景,词匹配,统计(敏感词检测,词检测),输入提示等,下面是代码节点节点代码publicclassNode{privateListnodeList=newArrayList<>();私人字符字;//这里保存了一个字符privateintisEnd=0;//这里是一个结束标记publicNode(charw){this.word=w;}publicNode(){}publicListgetNodeList(){returnnodeList;}publicvoidsetNodeList(ListnodeList){this.nodeList=nodeList;}publicchargetWord(){返回单词;}publicvoidsetWord(charword){this.word=word;}publicintgetIsEnd(){返回isEnd;}publicvoidsetIsEnd(intisEnd){this.isEnd=isEnd;}Node节点的关键点就是保存了char和isEnd这两个属性。这里我保存的是字符串,其实可以保存为utf8编码,防止一些编码问题。因为是多叉树结构,所以有可能sad和saddy这两个词需要结束标志。添加节点代码publicvoidaddNode(ListnodeList,char[]word){Listtemp=newArrayList<>();//遍历单词for(inti=0;i=0;j--){//如果有是子节点且单词相同,更新nodeList并跳出循环检查下一个单词if(j>0&&nodeList.get(j-1).getWord()==word[i]){nodeList=nodeList.get(j-1).getNodeList();休息;//如果子节点为零,则说明需要添加新节点}elseif(j==0){Noden=newNode(word[i]);//判断是否到达词尾,加一个flagif(nodeList.size()==0&&(i==word.length-1)){n.setIsEnd(1);}temp=n.getNodeList();nodeList.add(n);//nodeList被分配给一个新的节点,结束循环nodeList=temp;}}}}这一段要注意一点,我用的是List的数据结构,可以优化成Map结构,Hash表的时间复杂度是O(1)搜索词publicbooleansearchNode(ListnodeList,char[]word){for(inti=0;i=0;j--){if(nodeList.get(j).getWord()==word[i]){//word在末尾,有flag,则直接返回if((i==word.length-1)&&nodeList.get(j).getIsEnd()==1){返回真;}nodeList=nodeList.get(j).getNodeList();休息;}}}returnfalse;}SearchTextpublicbooleansearchText(ListnodeList,char[]word){//记录头节点Listhead=nodeList;for(inti=0;i=0;j--){if(nodeList.get(j).getWord()==word[i]){//不判断word是否在搜索文本的末尾,检查直接返回结果if(nodeList.get(j).getIsEnd()==1){return真的;}不deList=nodeList.get(j).getNodeList();休息;}//当节点没有子节点,程序运行到这里时,将nodeList重置为头节点if(j==0){nodeList=head;}}}returnfalse;}处理敏感词,或者类似的函数应该做分词。如果不做分词,就会出现错误,比如MaryLouA.pushonewordback。这里我按顺序逐字查找。但是应该有相关的文本搜索算法结合字典树。可以提高效率。我在这里实现的是O(m*n)。上面也提到了可以优化到O(n),但是也比以前快了很多。例如,输入提示比每次都查询数据库要快得多。如果字典树更新不频繁,比如地名,可以将字典树转成json保存在Redis中。这可以被其他语言使用,并且比查询一次数据库然后构造它更快。如有错误,或有更好的优化建议,欢迎讨论。