(请尊重作者知识产权,在引用转载时请注明出处)
在很多情况下都需要过滤关键字的程序,比如短信网关检查下行的信息是不是合法信息,论坛的贴子包不包含非法关键字等等,通过这篇文章我给大家介绍一种比较简单高效的解决方案
首先要解决的是关键字库问题,我们这里指的不是如何去收集这些关键字,而是假设关键字库已经存在,我们如何存放这些关键字的问题,给我们的选择不多,要么是hash表,要么是二叉树,其他数据结构要么不便于维护要么搜索复杂度太高,这里我们用C++语言来实现,首先来定义一个管理关键字库的类
class CKeyWordManager
{
public:
// load 关键字到内存
bool load ();
// 查找data中有没有包含指定的关键字
bool find (const string & data);
private:
set <string> m_keyWordList;
int m_keyWordMaxLength; //最长关键字的长度
};
我们用一个set来存放所有的关键字列表,set是一种红黑树,是一种高效的搜索二叉树,当然这里也可以使用hash_set来实现
这程序的关键是在于find方法,data内容可能很大,而且可能调用频率很高,我们有必要采用一种高效的方法来实现这一功能,基本思路是这样的:首先从data的0字符查找,检查第0个字符有没有在m_keyWordList中出现,如果有,返回真,如果没有,继续检查第0个和第1个字符有没有在m_keyWordList中出现过,……一直检查到0~n(n=m_keyWordMaxLength)数据,请看源码:
bool CKeyWordManager::find(const std::string &key)
{
for (int n = 0; n < key.length (); ++n)
{
for (int i = 1; i < m_keyWordMaxLength && i + n < key.length (); ++i)
{
set <string>::iterator it = m_keWordList.find (key.substr (n, i));
if (it != m_keyWordList.end ())
return true;
}
}
return false;
}
在这个解决方案中,如果m_keyWordList中的key大小分布比较小的话效率会很好,但是如果m_keyWordMaxLength非常大,那这种算法的效率也非常低,关于m_keyWordMaxLength特别大的情况(一般超过了20)的解决方式,我会在下一片文章中介绍