敏感词过滤优化的解决方案
介绍
敏感词字库匹配其实是关键字的一种匹配。最简单想到的额方法就是,如果要匹配某个字符串,去遍历敏感字库,这是最简单粗暴的方式。但是很明显当字库很大时,比如有六十万条数据,那么这样一个字库去遍历是非常耗时的。那么就需要我们去通过数据结构去优化匹配的方式。
暴力法和利用字典优化的方式
暴力法
直接对敏感词库进行遍历,意义对比,去全字匹配。
static void DirectFilter(string word)
{
for (int i = 0; i < sensitiveArr.Length; i++) //遍历铭感词数组
{
if (word == sensitiveArr[i]) //测试查找"粉丝"敏感词
{
Console.WriteLine("匹配到敏感字: "+ word);
break; //匹配到之后,退出循环
}
}
}
利用字典优化的方式
核心思想,就是利用关键字去搜索。定义字典或者hashtable,kye是铭感词的首字符例如“粉”,val是所有以“粉”为首字符的敏感词组成的一个链表。这样处理之后,我们去搜索一个敏感词的时候,首先判断字典里有没有这个key,没有就直接结束,有就去遍历这个key对应的value,这样处理之后,每个敏感词可能只需要搜索几次,就能比对完,非常快。
//初始化字典
static void SensitiveDicInit()
{
for (int i = 0; i < sensitiveArr.Length; i++) //遍历数组
{
char key = sensitiveArr[i][0]; //首字符作为Key,首字符相同的铭感词组成的链表作为valu
if (worldsTab.ContainsKey(key)) //有key就直接add
{
worldsTab[key].Add(sensitiveArr[i]);
}
else //没有就新建一个list再add
{
List<string> tmpList = new List<string>();
tmpList.Add(sensitiveArr[i]);
worldsTab.Add(key, tmpList);
}
}
}
static void QuickFilter(string word) {
char key = word[0];
if (worldsTab.ContainsKey(key)) //查找首字符是否在字典,在就去遍历value对应的List,不在就说明不是铭感词
{
for (int i = 0; i < worldsTab[key].Count; i++) //遍历value对应的List
{
if (word == worldsTab[key][i])
{
Console.WriteLine("找到了对应的关键词: " + word);
return;
}
}
Console.WriteLine("没找到对应的关键词: " + word);
}
else {
Console.WriteLine("没找到首关键字 key: " + word[0]);
}
}
效果
我们在入口函数里面跑一下,测试一下匹配效率。
static void Main(string[] args)
{
sensitiveStr = File.ReadAllText(@"d:\temp.txt"); //从文件中读取出敏感字符串
sensitiveArr = sensitiveStr.Split(','); //处理成敏感词数组
Stopwatch watch = new Stopwatch(); //时间监测类,用来检测代码执行时间ms
watch.Start();
DirectFilter("粉丝");
watch.Stop(); //结束检测
Console.WriteLine("暴力方式匹配执行时长: " + watch.Elapsed.TotalMilliseconds); //输出暴力法执行时间ms
watch.Restart();
SensitiveDicInit();
watch.Stop();
Console.WriteLine("字典初始化执行时长: " + watch.Elapsed.TotalMilliseconds);
watch.Restart();
QuickFilter("粉丝");
watch.Stop();
Console.WriteLine("字典方式匹配执行时长: " + watch.Elapsed.TotalMilliseconds);
Console.ReadLine();
}
这里是效果图
可以看到暴力法匹配需要9.3796ms,优化过后的方法需要15.7792ms+0.3141ms,明显是优化后的方式慢了。但是,我们可以发现只是初始化比较耗时,真正的匹配只消耗了0.3ms。所以不难发现,但敏感词库足够大时,或则说需要进行多次匹配时,后者的优势就会体现出来了。
总结
这里只是一个小小的demo,只做了全字匹配,大家如果有兴趣,其实可以加上正则表达式,去完成真正意义上的过滤敏感词。欢迎评论探讨技术,我是程序员小虎。