锁定老帖子 主题:使用DFA实现文字过滤
该帖已经被评为良好帖
|
|
---|---|
作者 | 正文 |
发表时间:2009-03-01
我也用hash做过dfa,但是不是用在文字过滤里,而是用在工作流引擎里,用在工作流引擎里是没有问题的,不过用在高性能场景的文字过滤里,hash函数确实会消耗更多的cpu,从python的测试代码来看用hash方式消耗的时间是本文所给方法的2倍以上。这还是没有并发的场景。
不过用在工作流引擎里我觉得倒确实比较合适的。因为流程状态转化的时候不需要象文字过滤那样循环文字的长度,只要根据当前状态和动作+条件就能得到下一个状态,所以速度上是能够满足要求的。 |
|
返回顶楼 | |
发表时间: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状态。 |
|
返回顶楼 | |
发表时间: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数会变的异常大。 而且都是对象包对象。 |
|
返回顶楼 | |
发表时间:2009-03-03
最后修改:2009-03-03
不知道 PERFECT HASH 对这项工作有没有帮助?楼主有没有分析过?
-- 对这个领域不了解仔细想了一下,发现 PERFECT HASH 也没有用,就当我没说,呵呵 -- |
|
返回顶楼 | |
发表时间:2009-03-03
sdh5724 写道 javaeyebird 写道 ahuaxuan 写道 这种方法早想过了,不行滴 java里的正则是NFA实现的,由于NFA是不确定的自动机,event+state并不能准确的得到下一个state,所以性能上```,呵呵. 而且这种方式也不能准确的得到每个词汇出现的频率,这也是个大问题. 晕,NFA和DFA是等价的。。。。 正则表达式完全可以做到关键字过滤,当然sun jre的正则实现,效率不怎么样 所以,你的原话: 引用 看到这里,没有接触过的同学可能会想到contains,正则之类的方法,但是很遗憾,这些方法都是行不通的
对没有接触过的同学,会产生误导,应该说是"....contains,jre的正则实现...这些方法的效率都是太差的..." 谁要能正则做到DFA 关键字匹配效率的效率. 我就转行. 建议考虑直接出家~~~ |
|
返回顶楼 | |
发表时间:2009-03-04
我是是完成过整个代码的, 信不信随便楼上的了。
|
|
返回顶楼 | |
发表时间:2009-03-12
上W的违禁词?这个从社会生活的领域来看,是不可能的吧,如果这样,大家就不用说话啦,呵呵。
估计这个量到K级别就很多很多啦。 |
|
返回顶楼 | |
发表时间:2009-03-12
首先,我声明一下我的政治态度:
我反对限制言论自由的行为。 然后,我想说的是: 短期山寨是可以的,但是不要长期山寨下去。在串匹配领域早已经有一大堆成熟的算法,最起码像AC、WM这些算法应该听说过才对,而不是发明方形的轮子。想扫盲的,看看这本书吧: http://www.dcc.uchile.cl/~gnavarro/FPMbook/ 中文版名字叫《柔性字符串匹配》。 |
|
返回顶楼 | |
发表时间:2009-03-12
最后修改:2009-03-12
joshzhu 写道 首先,我声明一下我的政治态度:
我反对限制言论自由的行为。 然后,我想说的是: 短期山寨是可以的,但是不要长期山寨下去。在串匹配领域早已经有一大堆成熟的算法,最起码像AC、WM这些算法应该听说过才对,而不是发明方形的轮子。想扫盲的,看看这本书吧: http://www.dcc.uchile.cl/~gnavarro/FPMbook/ 中文版名字叫《柔性字符串匹配》。 我也声明我的政治态度,我更坚决反对言论自由,这一点俺们是一致得 对于AC算法,我也刚刚也上网找了一点资料,那我先贴点我找到的: 引用 AC的局限性是对空间需求比较大,如果匹配模式太多,会造成空间的大量占用,甚至系统崩溃。所以在模式有限不多的模式下,AC是能够很好满足需求的要求的。
其实我在主贴也说过这样的话,再来一段呗: 引用 AC自动机匹配算法基于一种精巧的模式树(Trie)性质的一棵树
本文的算法也是这样呢(注意名字:使用DFA实现文字过滤),只是无意中出奇的类似,难道本文就是山寨版的AC? 只是俺之前不知道AC也是这种思路而已,难道是不识庐山真面目,只缘身在此山中 |
|
返回顶楼 | |
发表时间:2009-03-15
xdsnet 写道 上W的违禁词?这个从社会生活的领域来看,是不可能的吧,如果这样,大家就不用说话啦,呵呵。
估计这个量到K级别就很多很多啦。 这个算法不仅仅可以用在违禁词过滤上, 实际上, 在分词中用的最多的。 上百万的词汇, 随便就有了。 开拓点思路吧。 |
|
返回顶楼 | |