使用Hashtable实现简单的关键字过滤

 

这段时间开发一个聊天室,需要使用到关键字过滤的功能,需求如下:

1.将关键字替换成“*”;

2.支持过滤HTML,例如,S<span>B</span>也要过滤掉。

原本打算使用String.Replace来实现,但是这样的话,如果关键字很多,例如1000个,用以下方式:

for(int i=0;i<1000;i++)

{

    replace….
}

来实现,性能显然很低。因此,换了一种方法,用了Hashtable来提高过滤的性能。大概思路如下:

根据所有关键字建好用Hashtable数据结构,也可以理解为建立索引,之后每次过滤都用这个来进行:

例如,有以下几个关键字: SB , SX, Fuck, AB, ABC,那么用于过滤的数据结构如下:

image

上图中每个黑色方框代表一个hashtable,里面的字母就是hashtable的key,每个key都指向另一个hashtable,例如,第一个hashtable中就包含了3个Key,分别是S,A,F。每个关键字中的每个字符都被分散的放到hashtable中。

下面举例如何过滤

1.处理字符串 SB:第一个字母在第一级的hashtable中找到,而B也可以在S指向的Hashtable中找到,B指向的Hashtable中包括0,则,SB符合关键字,过滤掉。

2.处理字符串 SF:虽然S在第一级hashtable中可以找到,但是S指向的hashtable中没有F,所以,SF不是关键字

具体代码如下:

static class FilterWordUtil  
{
static Hashtable FilterWords = new Hashtable();
public static void AddFilterWord(string word)
{
Hashtable h = FilterWords;
foreach (char c in word.ToUpper())
{
if (!h.ContainsKey(c)) h[c] = new Hashtable();
h = h[c] as Hashtable;
}
h[0] = new Hashtable();
}

static int Match(string content, int index, out StringBuilder alt)
{
content = content.ToUpper();
alt = new StringBuilder();
bool filterChar = true;

Hashtable h = FilterWords;
int i = index;
for (; i < content.Length; i++)
{
char c = content[i];
switch (c)
{
case '<':
{
filterChar = false;
break;
}
case '>':
{
filterChar = true;
break;
}
case ' ':
{
break;
}
default:
{
if (filterChar)
{
if (h.ContainsKey(c))
{
h = h[c] as Hashtable;
c = '*';
}
else
{
if (!h.ContainsKey(0)) return -1;
}
}
break;
}
}
alt.Append(c);
if (h.ContainsKey(0)) return i;
}
return h.ContainsKey(0) ? i : -1;
}

public static String Filter(string content)
{
lock (FilterWords)
{
StringBuilder result = new StringBuilder();
bool filterChar = true;

for (int i = 0; i < content.Length; i++)
{
char c = content[i];
switch (c)
{
case '<':
{
filterChar = false;
break;

}
case '>':
{
filterChar = true;
break;
}
default:
{
if (filterChar)
{
StringBuilder temp;
int fi = Match(content, i, out temp);
if (fi != -1)
{
i = fi;
result.Append(temp);
continue;
}
}
break;
}
}
result.Append(c);
}

return result.ToString();
}
}
}

测试代码:

   1:  //添加关键字
   2:  FilterWordUtil.AddFilterWord("SB");
   3:  FilterWordUtil.AddFilterWord("SX");
   4:  FilterWordUtil.AddFilterWord("fuck");
   5:  FilterWordUtil.AddFilterWord("fuck you");
   6:  FilterWordUtil.AddFilterWord("天朝");
   7:  //过滤
   8:  string new_html = FilterWordUtil.Filter("你是SB,天<span>朝</span>");
   9:  Console.WriteLine(new_html);

过滤效果如下:

image

看到这里,有些读者要担心了,用了这么多的hashtable,会不会占用很多内存?当时也考虑过这问题,测试了1000多个关键字,建数据结构后,内存大概增加了几M,还不算太多。

 

 

转载至http://www.cnblogs.com/lucc/archive/2011/06/30/2093898.html

 

 

转载于:https://www.cnblogs.com/wavegui/archive/2012/01/20/2328084.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值