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(); } }
执行结果如下: