论坛首页 综合技术论坛

使用DFA实现文字过滤

浏览 71877 次
该帖已经被评为良好帖
作者 正文
   发表时间:2009-05-21   最后修改:2009-05-21
灰~机 写道
ahuaxuan 写道

1000个小case了,6w个关键字在jvm占用180m的内存。还说得过去。

写了个PHP的该算法,又用php的array特性,缩小了Trie树占的内存量。效率还算过得去
比preg_match_all那个正则方法效率高6倍左右




pantiansheng 写道
楼主
请教个问题
在实时情况下
如何保证重新加载同步问题

只能重建这颗书,建完之后替换树,呵呵
0 请登录后投票
   发表时间:2009-05-21  
ahuaxuan 写道
灰~机 写道
ahuaxuan 写道

1000个小case了,6w个关键字在jvm占用180m的内存。还说得过去。

写了个PHP的该算法,又用php的array特性,缩小了Trie树占的内存量。效率还算过得去
比preg_match_all那个正则方法效率高6倍左右




pantiansheng 写道
楼主
请教个问题
在实时情况下
如何保证重新加载同步问题

只能重建这颗书,建完之后替换树,呵呵



这个我也考虑过
就是觉得这样的话系统有一段时间占用的内存过大
不过不这样的话
也没有什么好的办法
我测了一下我的
2w个关键字
大约需要23M内存
0 请登录后投票
   发表时间:2009-05-21  
pantiansheng 写道

这个我也考虑过
就是觉得这样的话系统有一段时间占用的内存过大
不过不这样的话
也没有什么好的办法
我测了一下我的
2w个关键字
大约需要23M内存


看了一下,不需要重新构造,只需要把新增的关键词拿出来,执行建树时for循环里的代码就可以了
0 请登录后投票
   发表时间:2009-05-21  
删除,或者修改的时候还是比较麻烦的
0 请登录后投票
   发表时间:2009-05-23   最后修改:2009-05-23
20多M内存不算什么了.  这个算法应该是最快的了. O(N)的复杂度. 难道还能写出log(N)的复杂度?  这个算法唯一是在增加和删除, 内存压缩, 内存利用效率上, 看你怎么写程序了. 但是国外有不少关于这个算法增强的paper, 文化低, 看的不是很明白.

这个算法结合动态规划算法 能做出比较精确的中文分词---非专业分词使用是相当好了. 我在实现过一部分:)

很不想做文字过滤....可还是做了. 不然天朝锦衣卫天天找你家麻烦.
0 请登录后投票
   发表时间:2009-11-18  
我用java写了一个,直接基于字符构造一个树、
public class DFA {
	private String[] arr = {"DFA", "恶心", "DA"};
	private Node rootNode = new Node('R');
	
	private String content = "Hello DFA World DFA, HaHa! 恶心";
	
	private List<String> words = new ArrayList<String>();   
	private List<String> word = new ArrayList<String>();
	int a = 0;
	
	private void searchWord() {
		char[] chars = content.toCharArray();
		Node node = rootNode;
		while(a<chars.length) {
			node = findNode(node,chars[a]);
			if(node == null) {
				node = rootNode;
				a = a - word.size();
				word.clear();
			} else if(node.flag == 1) {
				word.add(String.valueOf(chars[a]));
				StringBuffer sb = new StringBuffer();
				for(String str : word) {
					sb.append(str);
				}
				words.add(sb.toString());
				a = a - word.size() + 1;
				word.clear();
				node = rootNode;
			} else {
				word.add(String.valueOf(chars[a]));
			}
			a++;
		}
	}
	
	private void createTree() {
		for(String str : arr) {
			char[] chars = str.toCharArray();
			if(chars.length > 0)
				insertNode(rootNode, chars, 0);
		}
	}
	
	private void insertNode(Node node, char[] cs, int index) {
		Node n = findNode(node, cs[index]);
		if(n == null) {
			n = new Node(cs[index]);
			node.nodes.add(n);
		}
		
		if(index == (cs.length-1))
			n.flag = 1;
			
		index++;
		if(index<cs.length)
			insertNode(n, cs, index);
	}
	
	private Node findNode(Node node, char c) {
		List<Node> nodes = node.nodes;
		Node rn = null;
		for(Node n : nodes) {
			if(n.c==c) {
				rn = n;
				break;
			}
		}
		return rn;
	}
	
	public static void main(String[] args) {
		DFA dfa = new DFA();
		dfa.createTree();
		dfa.searchWord();
		System.out.println(dfa.words);
	}
	
	
	private static class Node {
		public char c;
		public int flag; //1:表示终结,0:延续
		public List<Node> nodes = new ArrayList<Node>();
		
		public Node(char c) {
			this.c = c;
			this.flag = 0;
		}
		
		public Node(char c, int flag) {
			this.c = c;
			this.flag = flag;
		}
	}
}

0 请登录后投票
   发表时间:2009-11-19  
ahuaxuan 写道
to 楼上:

你是把while改成xrange吗??
同学,这样改有bug的

   
for a in xrange(10):
        print a
        a = a + 5

这段代码输出的是0-9,也就是说a=a+5并没有影响到xrange里的a,它之所以变快是因为改成这样会跳过很多byte,所以看上去变快了

In [1]: for a in range(10):
   ...:     print a
   ...:     a = a + 5
   ...:
0
1
2
3
4
5
6
7
8
9

In [2]: for a in xrange(10):
   ...:     print a
   ...:     a = a + 5
   ...:
0
1
2
3
4
5
6
7
8
9
0 请登录后投票
   发表时间:2009-11-19  
mikeandmore 写道
ahuaxuan 写道
to 楼上:

你是把while改成xrange吗??
同学,这样改有bug的

   
for a in xrange(10):
        print a
        a = a + 5

这段代码输出的是0-9,也就是说a=a+5并没有影响到xrange里的a,它之所以变快是因为改成这样会跳过很多byte,所以看上去变快了

In [1]: for a in range(10):
   ...:     print a
   ...:     a = a + 5
   ...:
0
1
2
3
4
5
6
7
8
9

In [2]: for a in xrange(10):
   ...:     print a
   ...:     a = a + 5
   ...:
0
1
2
3
4
5
6
7
8
9

我并没有说xrange有bug,你要仔细看一下我的代码,那句话是有上下文的。
0 请登录后投票
   发表时间:2009-12-04   最后修改:2009-12-04
text.txt:
中国人
words.txt:
中国
中国人

result:
cost time :  0.0160000324249
I have find some words as  1
中国 1

这种情况有问题的,而且不能以ab,bc这种情况来回退.
请问楼主如何处理?

再复杂一点:
words.txt:
中国 国人 中国人

我期望的结果是:
中国 1
国人 1
中国人 1

请教一下要实现这种需求,应该在算法上做些什么改进?
0 请登录后投票
   发表时间:2009-12-10  
pantiansheng 写道
楼主
你这样做还有一个问题
你采用GBK编码
假如某个代检查的文本的编码为:45,47,12,23,23,20
如果关键字中编码为:[b]47,12,23,23[/b]

红色标记处
这样会导致查询到了关键字,但是实际并不是关键字中的

我现在就遇到这个问题

还有个问题,我的违禁词汇是av,用户输入have,但是被检测出来了,这个该怎么改进
0 请登录后投票
论坛首页 综合技术版

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