1【背景】
这个在网络上也叫“敏感词过滤”,比如一些论坛、贴吧,涉及政治类词、骂爹骂娘的词,就得过滤掉。
我是闲着无聊,就看了下。
一开始想着用好几个replace不就好了吗,后来网上说这种效率太低了。
查了下,发现这一块还是比较深,最后我找了2种方法(方法是别人写的,从网上找的),都是精确匹配脏词的。效率如何不怎么关心,反正是有点意思的,所以想发一下。
(精确匹配脏词)这种方法得有个脏词库,目的就是将X文本出现的脏词替换掉。(还有人推荐了一种用贝叶斯公式替换脏词的,这种是靠概率,不是精确替换。有兴趣的可以了解下)
2【算法评论】
2.1叫它byte方法,也不知道有没有名字。代码里面对应——BadWordsFilter。
该算法的亮点是fastCheck,它代表某个脏字,在所有脏词里,曾出现的位置,比较机巧。因为它是位置信息,在检测脏词的时候有优势,可以减少判断。
缺点是fastCheck里有很多无用位置,并且因为它是byte,导致脏词长度最多只能有8位。
因为这些缺点,我试着改了下——BadWordsFilter2。改了以后好像变慢了许多。
2.2Tire(前缀树)方法
亮点就是前缀树结构了,不了解该结构的可以去百度下。
还有就是这个方法简单、好写。比上一个方法要好写。
3【结果评价】
哪个方法更好就不说了,实现的东西都不同,没有可比性。
但是为什么我的BadWordsFilter2会比原版的慢那么多?一个是4.0001ms,一个是1.0001ms。
从我开始写代码,就不怎么会测效率问题。还是机巧的方法更能激起我的兴趣。
这种byte表示位的思想,以前有遇到过,比如:5个数里取3个。可以写成单循环(2^6-1次),像10110,有3个1的就可以取。
4【代码】
using System;
using System.Collections.Generic;
using System.Collections;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
DateTime dt1 = DateTime.Now;
string[] keywords = new string[] { "林*", "敏感词", "过滤", "公安" };
var text = @"手机版| 敏感词收藏本站
网站首页
政务公开
网上办事
互动交流
专题专栏
帮助中心
我要咨询
常见问题
站点地图
手机门户
关于我们
联系我们
评比统计
导航链接
收藏本站收藏本站|关于我们|联系我们|站点地图|评比统计|手机门户
闽ICP备号 公安备案号";
#region 叉树算法部分
Trie trie = new Trie();
foreach (string keyword in keywords) trie.Add(keyword);
int size = 0;
int researchCount = 0;//总共搜索到的次数
size += text.Length;
string foundKeyword = null;
for (int i = 0; i < text.Length ; i++)
{
object token = null;
for (int j = i; j < text.Length; j++)
{
char charChild = text[j];
if (trie.Exist(charChild, ref token))//trie.Exist这个是关键函数了
{
foundKeyword = text.Substring(i, j - i + 1);
Console.WriteLine(" 字符出现的位置下标(从0开始):" + i + "到" + j + " 搜索到字符串:" + foundKeyword);
researchCount++;
i = j;//跳过中间的j-i个位置