敏感词替换,基于DFA算法,最快只需要读一遍文章即可完成替换敏感词,最差相当于读两遍文章

来源:互联网 发布:收银进销存软件 编辑:程序博客网 时间:2024/05/17 22:12

最近想自己搞点事情,就看到了敏感词过滤,搜索网络上面的过滤方法,很多,虽然说有轮子了,但是还是想自己造一个,看看能不能把速度优化一下

我写的方法直接对敏感词进行替换,不包含查询文章中有的敏感词等其他方法,如果有想写的请自行书写,这个对于我来说就够用了

不多说了,直接上代码吧

package Util;import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.InputStreamReader;import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.Map;import java.util.Set;/** * 敏感词过滤 基于DFA算法,时间复杂度我不会算,最快只需要读一遍文章即可,最差相当于读两遍文章* @ClassName: SensitiveFiltering* @Description: TODO(敏感词过滤)* @author toy* @date 2017年1月5日 下午4:51:23* */public class SensitiveFiltering {public HashMap SensitiveMap = null;@SuppressWarnings({ "rawtypes", "unchecked" })private void addSensitiveWordToHashMap(Set<String> keyWordSet) {// 敏感词map集合SensitiveMap = new HashMap(keyWordSet.size()); // 初始化敏感词容器,减少扩容操作// 迭代keyWordSetIterator<String> iterator = keyWordSet.iterator();while (iterator.hasNext()) {//敏感词字符串String key = iterator.next(); //生成敏感词节点的map,一直是最里面的节点Map nowMap = SensitiveMap;//开始分词for (int i = 0; i < key.length(); i++) {//取出对应字符char keyChar = key.charAt(i);//查找当前子map里面是否有存在的keyObject wordMap = nowMap.get(keyChar);// 如果存在该key,直接赋值if (wordMap != null) {nowMap = (Map) wordMap;} else {// 不存在则,则构建一个map,同时将isEnd设置为0,因为他不是最后一个Map<String, Boolean> newWorMap = new HashMap<String, Boolean>();// 不是最后一个newWorMap.put("isEnd", false);// 把节点添加到子map中nowMap.put(keyChar, newWorMap);//因为要设置下一个节点,所以要把当前子节点设置的节点传递给即将生成节点的mapnowMap = newWorMap;}if (i == key.length() - 1) {//如果是最后一个,根据map特性,直接用相同key替换掉nowMap.put("isEnd", true);}}}}/** * 本方法想法来自网络,集合生成算法由网络中@author chenming 实现  * 替换算法是在网络上面看到的一个想法,自己想搞定 * 时间复杂度我也不知道是多少,最差情况是每个字读两次,最优情况则过一边文章即可 * 模拟过滤31114个字符完成全部替换需要50毫秒左右 * 暂时没有发现漏查情况 * * @Title: checkSensitive* @Description: TODO(检查并替换敏感词)* @param @param param需要检查的字符串* @param @param replaceString    替换的字符* @author toy* @return String    返回类型* @throws */public String checkSensitive(String param, String replaceString) {//敏感词子节点Map nowMap = SensitiveMap;//是否开始匹配敏感词标示boolean startflag = false;//敏感词匹配是否结束标示boolean endflag =false;//是否完成匹配标示boolean flag = true;//最终生成对象sb对象StringBuffer sb = new StringBuffer();//临时变量,用来存储可能是敏感词的字StringBuffer temp1 = new StringBuffer();//临时变量,用来存储可能是敏感词的字的替换符号StringBuffer temp2 = new StringBuffer();for(int i=0;i<param.length();i++){//得到单个字char p = param.charAt(i);//查找是否在集合中nowMap = (Map) nowMap.get(p);//如果有敏感词开头,应该记录下来当前位置开始之后的数据,并且不能直接保存到sb对象中if(nowMap != null){//先把字和对应的替换符号记录下来temp1.append(p);temp2.append(replaceString);//修改是否开始匹配状态为开始if(!startflag){startflag=true;}//是否完成匹配标示flag = false;//判断是否是敏感词if((Boolean)nowMap.get("isEnd")){//敏感词匹配结束endflag = true;//把敏感词map重新赋值nowMap = SensitiveMap;}}else{//记录不进入敏感词的单词temp1.append(p);//设置是否敏感词为falseendflag = false;//设置是否完成匹配,因为都不是敏感词,所以是完成匹配flag = true;//把敏感词map重新赋值nowMap = SensitiveMap;}//判断是否已经开始进行敏感词匹配了if(startflag){//有开始有结尾,那么这个是敏感词,追加成*号if(endflag){//System.out.println(temp2.toString()+"----2");sb.append(temp2.toString());startflag=false;endflag =false;temp1.delete(0, temp1.length());temp2.delete(0, temp2.length());}else{//否则的话在判断是否已经完成敏感词匹配,如果完成了那么证明不是敏感词,直接把词追加进sb对象中if(flag){//System.out.println(temp1.toString()+"----1");sb.append(temp1.toString());startflag=false;endflag =false;temp1.delete(0, temp1.length());temp2.delete(0, temp2.length());}else{//如果没有完成敏感词匹配,可能是单个字,需要判断是否能组成一个词if(nowMap.get(param.charAt(i+1))==null){//不能组成那么就直接追加到sb对象,能则不处理,继续执行循环sb.append(temp1.toString());startflag=false;endflag =false;temp1.delete(0, temp1.length());temp2.delete(0, temp2.length());//把敏感词map重新赋值nowMap = SensitiveMap;}}}}else{//如果都没有进入匹配敏感词,那么直接追加即可//System.out.println(temp1.toString()+"----1");sb.append(temp1.toString());startflag=false;endflag =false;temp1.delete(0, temp1.length());temp2.delete(0, temp2.length());}}return sb.toString();}public Set<String> readSensitiveWordFile() throws Exception{Set<String> set = null;File file = new File("D:\\222.txt");    //读取文件InputStreamReader read = new InputStreamReader(new FileInputStream(file),"GBK");try {if(file.isFile() && file.exists()){      //文件流是否存在set = new HashSet<String>();BufferedReader bufferedReader = new BufferedReader(read);String txt = null;while((txt = bufferedReader.readLine()) != null){    //读取文件,将文件内容放入到set中set.add(txt);    }}else{         //不存在抛出异常信息throw new Exception("敏感词库文件不存在");}} catch (Exception e) {throw e;}finally{read.close();     //关闭文件流}return set;}public String readSensitiveWordFiles() throws Exception{StringBuffer sb =  new StringBuffer();File file = new File("D:\\ceshi.txt");    //读取文件InputStreamReader read = new InputStreamReader(new FileInputStream(file),"GBK");try {if(file.isFile() && file.exists()){      //文件流是否存在BufferedReader bufferedReader = new BufferedReader(read);String txt = null;while((txt = bufferedReader.readLine()) != null){    //读取文件,将文件内容放入到set中sb.append(txt);}}else{         //不存在抛出异常信息throw new Exception("敏感词库文件不存在");}} catch (Exception e) {throw e;}finally{read.close();     //关闭文件流}return sb.toString();}public static void main(String[] args) throws Exception {//Set<String> str = new HashSet<String>();//str.add("嘻嘻");SensitiveFiltering s = new SensitiveFiltering();Set<String> str = s.readSensitiveWordFile();s.addSensitiveWordToHashMap(str);//System.out.println(s.SensitiveMap.toString());String temp = s.readSensitiveWordFiles();System.out.println(temp.length());long start = System.currentTimeMillis();String txt = s.checkSensitive(temp,"*");System.out.println(txt);long end = System.currentTimeMillis();System.out.println(end-start);}}

0 0
原创粉丝点击