Trie树-脏词过滤应用

Trie树,又称字符查找树、前缀树,主要用于字符匹配(详见http://en.wikipedia.org/wiki/Trie)。适合做关键词查找,比如查找文章中的关键字然后给他们加链接。 当然对脏词的过滤应用也是样,只是把替换连接的工作换成了替换字符。

当前的代码还只是进行简单的替换,并没有做一些字符的处理,比如“昨天见到你妈,逼我要买房”,这本身不是脏词,因为有逗号,所以程序里要增加字符的范围判断。

程序中的skip就是用来过滤脏词的简单变体,比如“找*小*姐”,默认是最多跳过3个字符,这个可以随便调整了。总之是一个Trie的锻炼吧。

 

    public class TrieTree
    {
        private readonly Dictionary<char, TrieTree> Children;

        public bool End { get; set; }

        public TrieTree()
        {
            Children = new Dictionary<char, TrieTree>();
        }

        public void AddKey(string keyword)
        {
            if (String.IsNullOrEmpty(keyword))
            {
                return;
            }

            var cNode = this;

            foreach (var key in keyword)
            {
                if (cNode.Children.ContainsKey(key))
                {
                    cNode = cNode.Children[key];
                }
                else
                {
                    var node = new TrieTree();
                    cNode.Children.Add(key, node);
                    cNode = node;
                }
            }
            cNode.End = true;
        }


        public void Replace(ref string text)
        {
            for (var i = 0; i < text.Length; i++)
            {
                var cNode = this;
                var key = text[i];
                //碰到脏词的第一个词
                if (cNode.Children.ContainsKey(key))
                {
                    cNode = cNode.Children[key];
                    //查找是否包含脏词后面的词
                    var skip = 0;
                    for (var j = i + 1; j < text.Length; j++)
                    {
                        if (cNode.Children.ContainsKey(text[j]))
                        {
                            cNode = cNode.Children[text[j]];
                            skip = 0;
                        }
                        else
                        {
                            //允许略过过几个字符
                            skip++;
                            if (skip > 3)
                            {
                                break;
                            }
                        }
                        if (cNode.End)
                        {
                            var len = j + 1 - i;
                            text = text.Replace(text.Substring(i, len), string.Empty.PadLeft(len, '*'));
                            i += len;
                            break;
                        }
                    }
                }
            }
        }

    }

使用方法如下:

    class Program
    {
        static void Main(string[] args)
        {
            var trie = new TrieTree();
            var keywords = "我操,妓女,fuck".Split(',');
            foreach (var key in keywords)
            {
                trie.AddKey(key);
            }

            var text = @"我擦啊,尼玛,我操 你 妈,fuck you,你这个妓女,贱人。";
            trie.Replace(ref text);
            Console.WriteLine(text);
            Console.Read();
        }
    }

执行结果如下:

posted @ 2011-11-25 13:45  君之蘭  阅读(1392)  评论(1编辑  收藏  举报