DFA算法 处理屏蔽词库
春节之后,回来就连着上班,没休息过来那.简单整下吧。
这里是lua实现的。直接上代码。
--敏感词库转化关键词 dfa算法处理屏蔽词库 require "sensitive_words" ---词库 local SensitiveWordsUtil = class('SensitiveWordsUtil') function SensitiveWordsUtil:ctor() self:createTree() end --树节点创建 function SensitiveWordsUtil:createNode(c,flag,nodes) local node = {} node.c = c or nil --字符 node.flag = flag or 0 --是否结束标志,0:继续,1:结尾 node.nodes = nodes or {} --保存子节点 return node end --初始化树结构 function SensitiveWordsUtil:createTree() self.rootNode = self:createNode('R') --根节点 for i=1,#sensitive_words do local chars = self:getCharArray(sensitive_words[i]) if #chars > 0 then self:insertNode(self.rootNode,chars,1) end end end --插入节点 function SensitiveWordsUtil:insertNode(node,cs,index) local n = self:findNode(node,cs[index]) if n == nil then n = self:createNode(cs[index]) table.insert(node.nodes,n) end if index == #cs then n.flag = 1 end index = index + 1 if index <= #cs then self:insertNode(n,cs,index) end end --节点中查找子节点 function SensitiveWordsUtil:findNode(node,c) local nodes = node.nodes local rn = nil for i,v in ipairs(nodes) do if v.c == c then rn = v break end end return rn end --字符串转换为字符数组 function SensitiveWordsUtil:getCharArray(str) str = str or "" local array = {} local len = string.len(str) while str do local fontUTF = string.byte(str,1) if fontUTF == nil then break end --lua中字符占1byte,中文占3byte if fontUTF > 127 then local tmp = string.sub(str,1,3) table.insert(array,tmp) str = string.sub(str,4,len) else local tmp = string.sub(str,1,1) table.insert(array,tmp) str = string.sub(str,2,len) end end return array end --将字符串中敏感字用*替换返回 function SensitiveWordsUtil:warningStrGsub(inputStr) local chars = self:getCharArray(inputStr) local index = 1 local node = self.rootNode local word = {} while #chars >= index do --遇空格节点树停止本次遍历[*** -> ******] if chars[index] ~= ' ' then node = self:findNode(node,chars[index]) end if node == nil then index = index - #word node = self.rootNode word = {} elseif node.flag == 1 then table.insert(word,index) for i,v in ipairs(word) do chars[v] = '*' end node = self.rootNode word = {} else table.insert(word,index) end index = index + 1 end local str = '' for i,v in ipairs(chars) do str = str .. v end return str end --字符串中是否含有敏感字 function SensitiveWordsUtil:isWarningInPutStr(inputStr) local chars = self:getCharArray(inputStr) local index = 1 local node = self.rootNode local word = {} while #chars >= index do if chars[index] ~= ' ' then node = self:findNode(node,chars[index]) end if node == nil then index = index - #word node = self.rootNode word = {} elseif node.flag == 1 then return true else table.insert(word,index) end index = index + 1 end return false end return SensitiveWordsUtil
说明:
1、sensitive_words.lua是词库生成的lua文件。
可以根据提供的表格,使用脚本生成,这里不解释、
简单贴下,可以生成类似的格式(只是一个例子。可以使用更好的格式。)
sensitive_words = {} sensitive_words[1] = "敏感词1" sensitive_words[2] = "敏感词2" sensitive_words[3] = "敏感词3"
2、warningStrGsub 将字符串中敏感字用*替换返回
3、--isWarningInPutStr字符串中是否含有敏感字
看代码吧。网上一搜一大堆。了解原理就好。
这个比全部for循环效率高很多
测试发现,低端手机,依然会卡,所以采用 c++的方式实现一遍,比lua的效率要高。 敏感词太多的话,可以分批加载,分帧加载