论坛首页 综合技术论坛

使用DFA实现文字过滤

浏览 72206 次
该帖已经被评为良好帖
作者 正文
   发表时间:2009-03-01  
我也用hash做过dfa,但是不是用在文字过滤里,而是用在工作流引擎里,用在工作流引擎里是没有问题的,不过用在高性能场景的文字过滤里,hash函数确实会消耗更多的cpu,从python的测试代码来看用hash方式消耗的时间是本文所给方法的2倍以上。这还是没有并发的场景。

不过用在工作流引擎里我觉得倒确实比较合适的。因为流程状态转化的时候不需要象文字过滤那样循环文字的长度,只要根据当前状态和动作+条件就能得到下一个状态,所以速度上是能够满足要求的。
0 请登录后投票
   发表时间:2009-03-01  
在实际应用中,实时输出是没半点问题的,因为关键字树是全局的,
java的hashcode是int,而字符仅仅是char,也就是说char自己就是hash值。
如果说需要优化的话,也只需要初始化map的时候把容量分配大点,减少hash冲突即可。

还有就是不定制 CharHashMap的话,就为避免自动拆装箱产生太多临时对象。
需要对Character对象进行缓存,不试用自动拆装箱,而用数组下标来获取Character对象。

 static final Character cache[] = new Character[65536];

 static {
  for (int i = 0; i < cache.length; i++)
   cache[i] = new Character((char) i);
 }


Character 的hashcode方法是:
    public int hashCode() {
        return (int)value;
    }



sdh5724 写道
codeutil 写道
关键字过滤使用正则是死路一条.

现在有些时候连长七八十个字符的url地址都要加到关键字列表。

用hashmap将关键字库包装构造成多节点树,Hashmap的key是单个char,value是树节点,对文本进行树查找就可以了。

对char稍作转换,就可以实现按同音字过滤,或繁简体,或全半角,或非汉字字符隔开的,或火星文等,通杀。



对于过滤关键字, 估计你说的是够用了。 但是, 如果想做输出实时过滤, 还是困难了点。 HASH还是很消耗时间。 另外, 如果字典大了, 内存收集管理很消耗的, 节点会变的非常多, 对于DFA树, 本来用HASH是最容易表述的, 但是性能诧异还是很大。 最好的办法使用双数组表述DFA状态。

0 请登录后投票
   发表时间:2009-03-02  
codeutil 写道
在实际应用中,实时输出是没半点问题的,因为关键字树是全局的,
java的hashcode是int,而字符仅仅是char,也就是说char自己就是hash值。
如果说需要优化的话,也只需要初始化map的时候把容量分配大点,减少hash冲突即可。

还有就是不定制 CharHashMap的话,就为避免自动拆装箱产生太多临时对象。
需要对Character对象进行缓存,不试用自动拆装箱,而用数组下标来获取Character对象。

 static final Character cache[] = new Character[65536];

 static {
  for (int i = 0; i < cache.length; i++)
   cache[i] = new Character((char) i);
 }


Character 的hashcode方法是:
    public int hashCode() {
        return (int)value;
    }



sdh5724 写道
codeutil 写道
关键字过滤使用正则是死路一条.

现在有些时候连长七八十个字符的url地址都要加到关键字列表。

用hashmap将关键字库包装构造成多节点树,Hashmap的key是单个char,value是树节点,对文本进行树查找就可以了。

对char稍作转换,就可以实现按同音字过滤,或繁简体,或全半角,或非汉字字符隔开的,或火星文等,通杀。



对于过滤关键字, 估计你说的是够用了。 但是, 如果想做输出实时过滤, 还是困难了点。 HASH还是很消耗时间。 另外, 如果字典大了, 内存收集管理很消耗的, 节点会变的非常多, 对于DFA树, 本来用HASH是最容易表述的, 但是性能诧异还是很大。 最好的办法使用双数组表述DFA状态。




类似处理char的时候, 如果每个char都call一次函数, 你测试看看, 性能差别是多少。 以前我就用charAt(i)来处理String, 性能差别一倍。 hash对于dfa来说, 确实代码很容易写, 如果是给予dfa的分词基础系统,那就很恶心了, 如果你有一个1百万词汇的字典, 这个hash数会变的异常大。 而且都是对象包对象。

0 请登录后投票
   发表时间:2009-03-03   最后修改:2009-03-03
不知道 PERFECT HASH 对这项工作有没有帮助?楼主有没有分析过?
-- 对这个领域不了解仔细想了一下,发现 PERFECT HASH 也没有用,就当我没说,呵呵 --
0 请登录后投票
   发表时间:2009-03-03  
sdh5724 写道
javaeyebird 写道
ahuaxuan 写道

这种方法早想过了,不行滴
java里的正则是NFA实现的,由于NFA是不确定的自动机,event+state并不能准确的得到下一个state,所以性能上```,呵呵.

而且这种方式也不能准确的得到每个词汇出现的频率,这也是个大问题.

晕,NFA和DFA是等价的。。。。
正则表达式完全可以做到关键字过滤,当然sun jre的正则实现,效率不怎么样
所以,你的原话:
引用
看到这里,没有接触过的同学可能会想到contains,正则之类的方法,但是很遗憾,这些方法都是行不通的

对没有接触过的同学,会产生误导,应该说是"....contains,jre的正则实现...这些方法的效率都是太差的..."


谁要能正则做到DFA 关键字匹配效率的效率. 我就转行.


建议考虑直接出家~~~
0 请登录后投票
   发表时间:2009-03-04  
我是是完成过整个代码的, 信不信随便楼上的了。
0 请登录后投票
   发表时间:2009-03-12  
上W的违禁词?这个从社会生活的领域来看,是不可能的吧,如果这样,大家就不用说话啦,呵呵。
估计这个量到K级别就很多很多啦。
0 请登录后投票
   发表时间:2009-03-12  
首先,我声明一下我的政治态度:
我反对限制言论自由的行为。

然后,我想说的是:
短期山寨是可以的,但是不要长期山寨下去。在串匹配领域早已经有一大堆成熟的算法,最起码像AC、WM这些算法应该听说过才对,而不是发明方形的轮子。想扫盲的,看看这本书吧:
http://www.dcc.uchile.cl/~gnavarro/FPMbook/
中文版名字叫《柔性字符串匹配》。
0 请登录后投票
   发表时间:2009-03-12   最后修改:2009-03-12
joshzhu 写道
首先,我声明一下我的政治态度:
我反对限制言论自由的行为。

然后,我想说的是:
短期山寨是可以的,但是不要长期山寨下去。在串匹配领域早已经有一大堆成熟的算法,最起码像AC、WM这些算法应该听说过才对,而不是发明方形的轮子。想扫盲的,看看这本书吧:
http://www.dcc.uchile.cl/~gnavarro/FPMbook/
中文版名字叫《柔性字符串匹配》。


我也声明我的政治态度,我更坚决反对言论自由,这一点俺们是一致得

对于AC算法,我也刚刚也上网找了一点资料,那我先贴点我找到的:

引用
AC的局限性是对空间需求比较大,如果匹配模式太多,会造成空间的大量占用,甚至系统崩溃。所以在模式有限不多的模式下,AC是能够很好满足需求的要求的。


其实我在主贴也说过这样的话,再来一段呗:
引用
AC自动机匹配算法基于一种精巧的模式树(Trie)性质的一棵树


本文的算法也是这样呢(注意名字:使用DFA实现文字过滤),只是无意中出奇的类似,难道本文就是山寨版的AC?

只是俺之前不知道AC也是这种思路而已,难道是不识庐山真面目,只缘身在此山中
0 请登录后投票
   发表时间:2009-03-15  
xdsnet 写道
上W的违禁词?这个从社会生活的领域来看,是不可能的吧,如果这样,大家就不用说话啦,呵呵。
估计这个量到K级别就很多很多啦。



这个算法不仅仅可以用在违禁词过滤上, 实际上, 在分词中用的最多的。  上百万的词汇, 随便就有了。

开拓点思路吧。
0 请登录后投票
论坛首页 综合技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics