现在的游戏有敏感词检测这一点,相信大家也不陌生了,不管是聊天,起名,签名还是简介,只要是能让玩家手动输入的地方,一定少不了敏感词识别,至于识别之后是拒绝修改还是星号替换,这个就各有各的做法了,但是绕不开的一定是需要高效的敏感词检测机制。
相信大家对于游戏里聊天框的以下内容已经不陌生了
一个垃圾的游戏环境是非常影响玩游戏的心情的,看到这些***,就知道游戏已经帮我们屏蔽掉了那些屏蔽字了,对于玩游戏而言,心里会好受很多。敏感词识别对于游戏的重要性不言而喻。当然,除了游戏,也有很多业务场景可能需要敏感词检测,如果你接到这样一个需求的时候,你会怎么做?
作为Java程序员,我的第一反应,一定是使用jdk原生的String类提供的contain或replace方法来进行包含判断或字符替换,这是最简单直接的方式。那我们就来看看String的实现方式:
String在java中以char数组形式存储,而String.contains的实现,实际上是对数组的遍历查找匹配
// 最终调用方法
static int indexOf(char[] source, int sourceOffset, int sourceCount,
char[] target, int targetOffset, int targetCount,
int fromIndex) {
// ...
}
String.replace有4个接口,实现为正则匹配替换或直接遍历替换
public String replace(char oldChar, char newChar) {
// 直接进行字符串遍历,替换第一个匹配的字符串
}
public String replace(CharSequence target, CharSequence replacement) {
// 创建Pattern,使用LITERAL模式进行正则匹配替换replaceAll
// 当设置LITERAL标志时,输入字符串中的所有字符都被视为普通字符。
// 这意味着正则表达式的特殊字符,如点号(.)、星号(*)、加号(+)等,都将失去它们在正则表达式中的特殊意义,被直接视为普通字符。
}
public String replaceAll(String regex, String replacement) {
// 创建Pattern,使用正则表达式模式匹配替换replaceAll
}
public String replaceFirst(String regex, String replacement) {
// 创建Pattern,使用正则表达式模式匹配替换replaceFirst,仅替换第一个匹配的字符串
}
通过jdk提供的String源码我们可以得到以下结果:
其他语言的字符串操作API大同小异,具体看源码的实现方式
另外一种我们能想到的方式就是进行正则表达式的匹配了。前面提到,在java中如果使用String的api,它有部分接口就是使用正则表达式来实现的。
使用正则表达式有一定优势,也有一定缺陷。这就不得不提正则表达式的实现原理:FA(Finite Automaton:有限自动机)
FA又分为DFA和NFA,我们以正则ab|ac举例
NFA(Nondeterministic finite automaton:非确定性有限状态自动机)
在NFA中表达式会构建为以下结构
DFA(Deterministic finite automaton:确定性有限自动机)
在DFA中表达式会构建为以下结构