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

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

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

不多说了,直接上代码吧

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()); // 初始化敏感词容器,减少扩容操作
		// 迭代keyWordSet
		Iterator<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里面是否有存在的key
				Object 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);
					//因为要设置下一个节点,所以要把当前子节点设置的节点传递给即将生成节点的map
					nowMap = 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);
				//设置是否敏感词为false
				endflag = 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);
	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值