DFA算法过滤敏感词

数据结构


public class Word implements Comparable<Word>{

	public char c;

	public MyList next = new MyList();

	public boolean flag = false;

	public Word(char c){
		this.c = c;
	}

	public boolean isFlag() {
		return flag;
	}

	public void setFlag(boolean flag) {
		this.flag = flag;
	}

	@Override
	public int compareTo(Word word) {
		return c - word.c;
	}
}


import java.util.ArrayList;

/**
 *
 */
public class MyList extends ArrayList<Word> {

	public Word get(char c) {
		for (Word w : this) {
			if (w.c == c) {
				return w;
			}
		}
		return null;
	}

	/**
	 * 二分查找,必须先升序排序
	 *
	 * @param c 需要查找的字符
	 * @return Word对象:如果找到   null:如果没找到
	 */
	public Word binaryGet(char c) {
		int left, right, key;
		Word word;
		left = 0;
		right = this.size() - 1;
		while (left <= right) {
			key = (left + right) / 2;
			word = get(key);
			if (word.c == c) {
				return word;
			} else if (word.c > c) {
				right = key - 1;
			} else {
				left = key + 1;
			}
		}
		return null;
	}

	public Word add(char c) {
		Word word = new Word(c);
		super.add(word);
		return word;
	}

}

具体实现


import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.Collections;
import java.util.List;
import java.util.Objects;

@Slf4j
public final class SensitiveWordUtil {

	public static MyList wordList;

	// 替代字符
	private final static char replace = '*';


	//遇到这些字符就会跳过,例如,如果"AB"是敏感词,那么"A B","A=B"也会被屏蔽
	private final static char[] skip = new char[]{
			'!', '*', '-', '+', '_', '=', ',', '.', '@'
	};

	/**
	 * 敏感词替换
	 *
	 * @param text 待替换文本
	 * @return 替换后的文本
	 */
	public static boolean Filter(String text) {
		boolean flag = false;
		if (wordList == null || wordList.size() == 0) {
			log.info("the table of sensitive word is blank ");
			return flag;
		}
		// 把String转化成char数组,便于遍历
		char[] __char__ = text.toCharArray();
		int i, j;
		Word word;
		// 遍历所有字符
		endLoop:
		for (i = 0; i < __char__.length; i++) {
			char c = __char__[i];
			// 使用二分查找来寻找字符,提高效率
			word = wordList.binaryGet(c);
			// word != null说明找到了
			if (word != null) {
				if (word.flag) {
					//长度为1的敏感词
					flag = true;
					break;
				}
				j = i + 1;
				// 开始逐个比较后面的字符
				while (j < __char__.length) {
					// 跳过空格之类的无关字符
					if (skip(__char__[j])) {
						j++;
						continue;
					}
					// 判断下一个字符是否存在以及是否是结束标记位
					word = word.next.get(__char__[j]);
					if (word == null) {
						break;
					}
					if (word.flag) {
						flag = true;
						break endLoop;
					}
					j++;
				}
			}
		}
		return flag;
	}

	/**
	 * 加载敏感词列表
	 *
	 * @param words 敏感词数组
	 */
	public static void loadWord(List<String> words) {
		if (words == null) {
			return;
		}
		char[] chars;
		MyList now;
		Word word;
		wordList = new MyList();
		for (String __word__ : words) {
			if (StrUtil.isBlank(__word__)) {
				continue;
			}
			chars = __word__.toCharArray();
			now = wordList;
			word = null;
			for (char c : chars) {
				if (word != null) {
					if (word.next == null) {
						word.next = new MyList();
					}
					now = word.next;
				}
				word = now.get(c);
				if (word == null) {
					word = now.add(c);
				}
			}
			if (Objects.nonNull(word)) {
				word.setFlag(true);
			}
		}
		sort(wordList);
	}

	/**
	 * 对敏感词多叉树递增排序
	 *
	 * @param list 待排序List
	 */
	private static void sort(MyList list) {
		if (list == null) {
			return;
		}
		// 递增排序
		Collections.sort(list);
		for (Word word : list) {
			sort(word.next);
		}
	}

	/**
	 * 判断是否跳过当前字符
	 *
	 * @param c 待检测字符
	 * @return true:需要跳过   false:不需要跳过
	 */
	private static boolean skip(char c) {
		for (char c1 : skip) {
			if (c1 == c) {
				return true;
			}
		}
		return false;
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值