"****"肯定都见过吧,我们最先想到的肯定是暴力for循环,那如果敏感词足够多呢,那么其效率可想而知,最近进行学习时发现了可以利用字典树进行实现这一个步骤。
先来介绍下什么是字典树吧,与大多数树状结构无异,都是从根节点出发下面有子节点,对子节点的管理是通过一个字典来进行管理的,也就是map,说到这很多朋友就反应过来了,为了方便理解我给附上图,bi站上的动画做的通俗易懂。
2024-05-26 23-57-08
public class BolReplace {
private class TrieNode{
//该标志作为判断是否为敏感词结尾
private boolean isEnd=false;
//subNiodes主要是做节点存储
Map<Character,TrieNode> subNodes=new HashMap<>();
//用来获取下一个节点
public TrieNode getSubNode(Character c){
return subNodes.get(c);
}
//增加节点
public void addSubNode(Character c,TrieNode node){
subNodes.put(c,node);
}
//将敏感词结尾标志状态切换
public void setEnd(boolean end){
this.isEnd=end;
}
//用于后续判断是否为敏感词结尾
public boolean getIsEnd(){
return this.isEnd;
}
}
//敏感词替换符
private static final String DEFAULT_REPLACEMENT="***";
//根节点
private TrieNode root;
//空参构造,同时初始化字典树根节点
public BolReplace(){
root=new TrieNode();
}
//添加敏感词
public void addWord(String text){
if (text==null ||text.trim().equals("")){
return;
}
TrieNode curNode= root;
int length = text.length();
for (int i = 0; i < length; i++) {
Character c = text.charAt(i);
/获取子节点是否为空如果不为空,继续下次循环,如果为空,则在父节点上添加上本节点
TrieNode subNode = curNode.getSubNode(c);
if (subNode==null){
subNode = new TrieNode();
curNode.addSubNode(c,subNode);
}
//如果敏感词的已经到了结尾,则添加结尾标志
curNode=subNode;
if (i==length-1){
curNode.setEnd(true);
}
}
}
//这个方法用来晒筛选并替换敏感词
public String newLife(String text){
if (text==null||text.trim().equals("")){
return text;
}
String replacement = DEFAULT_REPLACEMENT;
StringBuilder result = new StringBuilder();
//所有筛选从主节点开始
TrieNode curNode=root;
//多个作用:1.便于标志敏感词位置,2、判断该词条是否筛选完成
int start=0;
int end=0;
while (end<text.length()){
Character c = text.charAt(end);
curNode = curNode.getSubNode(c);
//如果当前值并不存在上级节点中,便不是敏感词,并切换至根节点重新判断
if (curNode==null){
result.append(c);
end=start+1;
start=end;
curNode=root;
//如果当前值在在字典树中具有结标志,则进行替换
}else if (curNode.getIsEnd()){
result.append(replacement);
end=end+1;
start=end;
curNode=root;
//如果不满足上述条件说明当前节点存在在敏感词字典树中
且没到敏感词结尾标志
}else {
++end;
}
}
//然后进行拼接并返回
result.append(text.substring(start));
return result.toString();
}
//下面就是进行试验了,本人亲测是可以的
public static void main(String[] args) {
BolReplace bolReplace = new BolReplace();
bolReplace.addWord("ccc");
String s = bolReplace.newLife("aaacccddccc");
System.out.println(s);
}
}
具体实现呢我这已经描述的非常清楚了,有不懂的可以评论区回复,并且在写这篇文章时自己发现了个小bug,不知道有没有眼尖朋友看出来