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();
}
}
執行的結果: