xingd.net

.net related techonology
posts - 54, comments - 616, trackbacks - 6, articles - 2

.NET脏字过滤算法

Posted on 2007-09-26 03:57 xingd 阅读(4470) 评论(30)  编辑 收藏 网摘 所属分类: Framework

原文见http://www.cnblogs.com/goody9807/archive/2006/09/12/502094.html,很多网站都转载了。

但在我这里测试的时候,RegEx要快一倍左右。但是还是不太满意,因为我们网站上脏字过滤用的相当多,对效率已经有了一些影响,经过一番思考后,自己做了一个算法。在自己的机器上测试了一下,使用原文中的脏字库,0x19c的字符串长度,1000次循环,文本查找耗时1933.47ms,RegEx用了1216.719ms,而我的算法只用了244.125ms.

更新:新增一个BitArray,用于判断某char是否在所有脏字中出现过。总时间由244ms降到了34ms.

主要算法如代码所示

      private static Dictionary dic = new Dictionary();
      
private static BitArray fastcheck = new BitArray(char.MaxValue);

      
static void Prepare()
      {
          
string[] badwords =  // read from file
           foreach (string word in badwords)
            {
                
if (!dic.ContainsKey(word))
                {
                    dic.Add(word, 
null);
                    maxlength 
= Math.Max(maxlength, word.Length);
                    fastcheck[word[0]] = true;
                }
            }
      }

使用的时候

int index = 0;
while (index < target.Length)
{
    
if (!fastcheck[target[index]])
    {
        
while (index < target.Length - 1 && !fastcheck[target[++index]]) ;
    }

    
for (int j = 0; j < Math.Min(maxlength, target.Length - index); j++)
    {
        
string sub = target.Substring(index, j);
        
if (dic.ContainsKey(sub))
        {
            sb.Replace(sub, 
"***", index, j);
            index 
+= j;
            
break;
        }
    }

    index
++;
}

Feedback

#1楼   回复  引用  查看    

2007-09-26 08:55 by 针式个人知识库管理      
你的算法当然不如前两种灵活。业务规则的灵活比性能有时更重要

#2楼   回复  引用    

2007-09-26 08:56 by Faster[未注册用户]
为什么不一次把所有脏字都过滤完?

#3楼   回复  引用  查看    

2007-09-26 09:12 by Yok      
test:我们有两台独立的服务器

#4楼   回复  引用  查看    

2007-09-26 09:16 by 亚历山大同志      
一段一段的Replace和一次性全部Replace有啥区别呢?算法达人出来解释一下撒

#5楼   回复  引用  查看    

2007-09-26 09:24 by wingoo      
最近也在找一个关键字识别的算法..
这是昨天找到的,不过具体没有测试:)
http://www.codeproject.com/cs/algorithms/ahocorasick.asp" target="_new">http://www.codeproject.com/cs/algorithms/ahocorasick.asp

#6楼   回复  引用    

2007-09-26 09:32 by yun[未注册用户]
前缀树才是好办法,楼主你应该看看搜索引擎是怎么做的。 比你这个复杂M倍,快N倍

#7楼   回复  引用    

2007-09-26 09:36 by yun[未注册用户]
不过好一点的算法一般需要构建有限状态机进行多模式匹配。 脏字少了还好,多了话,你的算法太业余了。

#8楼[楼主]   回复  引用  查看    

2007-09-26 09:41 by xingd      
@针式个人知识库管理
需要有多灵活?跟原来两种算法,同样的输入,同样的输出,请解释下哪里缺失灵活性了。

@Faster
为了灵活性,比如加入/删除脏字,因此是在显示的时候再进行过滤的。

@wingoo
我之前考虑过同样的算法,但是似乎只有小字符集(英文)时建立keyword tree更优,对于中文来讲,不见得效率高。当然还是要看测试结果了。

#9楼[楼主]   回复  引用  查看    

2007-09-26 10:37 by xingd      
新增一个BitArray,用于判断某char是否在所有脏字中出现过。总时间由244ms降到了34ms.

在脏字数据量不大的情况下,比如原文中754个脏字的情况,这样的算法虽然业余,但是针对性强,跟搜索引擎还是有区别的,效率上来讲不一定会慢多少。

脏字当然会比较少,多了的话,网站就没法做了。我们网站的脏字也就100左右。

#10楼   回复  引用    

2007-09-26 10:54 by 古巴[未注册用户]
@xingd
当网络彻底被和谐后,我估计会有很多脏字,那时网站确实没法做了,所以大家早点做好准备吧:)

#11楼   回复  引用    

2007-09-26 11:35 by 吙煋囚[未注册用户]
@古巴
洳果采鼡吙煋攵,任何贓芓都昰鈳能漏網啲,ф攵洳此の靈活,防鈈勝防。與其障囻の目鈈洳使囻能辨.

#12楼   回复  引用    

2007-09-26 11:59 by 560889223[未注册用户]
...囧
火星 文

#13楼   回复  引用    

2007-09-26 12:27 by 路过[未注册用户]
只有发生更新的时候才去过滤,速度最重要么?灵活是最重要的。
应该是机制出现问题吧。

#14楼   回复  引用  查看    

2007-09-26 13:10 by 随风流月      
用 StringBuilder,看看效率。

#15楼[楼主]   回复  引用  查看    

2007-09-26 13:22 by xingd      
@路过
脏字会有变化

#16楼   回复  引用  查看    

2007-09-26 15:49 by Bob-wei      
--引用--------------------------------------------------
wingoo: 最近也在找一个关键字识别的算法..
这是昨天找到的,不过具体没有测试:)
<a href="http://www.codeproject.com/cs/algorithms/ahocorasick.asp"" target="_new">http://www.codeproject.com/cs/algorithms/ahocorasick.asp" target="_new">http://www.codeproject.com/cs/algorithms/ahocorasick.asp</a>" target="_new">http://www.codeproject.com/cs/algorithms/ahocorasick.asp</a>

--------------------------------------------------------
看了下,都是E文,慢慢学习吧

#17楼   回复  引用    

2007-09-26 22:38 by Kcaz[未注册用户]
如果有两组脏字,这两组脏字的前n个字相同,那么当真实输入的是较长的脏字,这个方法的结果如何呢?

#18楼   回复  引用  查看    

2007-09-27 08:53 by jecray      
@吙煋囚
这火星文怎么打出来的啊

#19楼[楼主]   回复  引用  查看    

2007-09-27 12:11 by xingd      
火星拼音输入法

#20楼   回复  引用    

2007-09-27 21:53 by w[未注册用户]
学习了!!

#21楼   回复  引用  查看    

2007-09-28 08:36 by 武眉博<活靶子.Net>      
特色

#22楼   回复  引用    

2007-09-28 14:01 by 古巴[未注册用户]
@吙煋囚
学习火星文是个好办法啊:)
不过,彻底和谐后,必然再给你来个实名上网之类,呵呵,如果谁胆敢发布不和谐的信息,就算是火星文,也得给你和谐了,你还敢辨:(

看来到时候还是彻底移民火星保险:)

#23楼   回复  引用  查看    

2007-09-28 18:17 by 钢钢      
.NET脏字过滤算法

#24楼   回复  引用    

2007-12-06 19:22 by wf[未注册用户]
原作者是谁啊,都在乱载,看不懂,给个清晰的例子好不?
对了应该是 private static Dictionary<String, String> dic = new Dictionary<String, String>();
估计你不是原作者

#25楼[楼主]   回复  引用  查看    

2007-12-06 19:41 by xingd      
我就是原作者啊,本文的代码只用来说明思路而已.

.NET 3.5里的HashSet才是最适合这里用的。

#26楼   回复  引用    

2007-12-14 09:44 by lvgga[未注册用户]
看不懂啊,, 能给个完整的代码吗??

#27楼[楼主]   回复  引用  查看    

2007-12-14 11:21 by xingd      
关键点:
1.构建2个BitArray(Char.Max)分别用于快速检索是否某一字存在于所有脏字的起始字和所有字中.
2.利用Hash来判断某一词是否在脏字中.

#28楼   回复  引用    

2007-12-17 15:21 by nass[未注册用户]
晕。。看不懂。 target和maxlength 都是干吗的,怎么没有定义啊??代码不全啊。。

#29楼   回复  引用    

2007-12-17 15:35 by 小化美[未注册用户]
同楼上,看不懂哦,虽说只是说明思路.. 楼主有时间加个注释吧.. :)

#30楼[楼主]   回复  引用  查看    

2007-12-17 16:01 by xingd      
target是要做过滤得原始文字
maxlength是最长的脏字长度



发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 906013




相关文章:

相关链接: