C++ 敏感词过滤的算法之DFA算法

DFA简介

DFA全称为:Deterministic Finite Automaton,即确定有穷自动机。其特征为:有一个有限状态集合和一些从一个状态通向另一个状态的边,每条边上标记有一个符号,其中一个状态是初态,某些状态是终态。但不同于不确定的有限自动机,DFA中不会有从同一状态出发的两条边标志有相同的符号。

在这里插入图片描述
在这幅图中大写字母(S、U、V、Q)都是状态,小写字母a、b为动作。通过上图我们可以看到如下关系
a b b
S -----> U S -----> V U -----> V

一、EX:匹配(我是中国人)

在这里插入图片描述
【匹配过程】:

初始状态为空,当触发事件“我”时转换到状态“我”;
触发事件“是”,转换到状态“我是”;
依次类推,直到转换为最后一个状态“我是中国人”。
再让我们考虑多个关键词的情况,例如“我是中国”、“我是中国魂”以及“我是中国军人”。
在这里插入图片描述
这样查找事件会走向特定的序列,当查找到末尾节点时 结束匹配 这样的话 我们替换需要屏蔽的词即可

所以我们的代码思路是将所有敏感词添加进敏感词树中,然后匹配时将敏感词依次放入敏感词树进行匹配
代码如下:

1.添加节点

void Filter::addWord(string keyWord, unsigned int keyWordErrLevel)
{
	TrieNode *tempNode = rootNode;
	for (int i = 0; i < keyWord.length(); i++)
	{
		string c = keyWord.substr(i, 1);
		TrieNode *node = tempNode->getSubNode(c);
		if (nullptr == node)
		{
			node = new TrieNode();
			tempNode->addSubNode(c, node);
		}
		tempNode = node;
		if (i == keyWord.length() - 1)
		{
			tempNode->setkeywordErrLevel(keyWordErrLevel);
		}
	}
}

2.匹配算法

代码如下(示例):

std::string Filter::filter(string text, unsigned int &textErrLevel)
{
	if (text.empty())
	{
		return text;
	}
	textErrLevel = 0;
	string result;				       
	string strNode;					    
	string replacement  = "***";      
	TrieNode*tempNode   = rootNode;    
	int beginIndex	    = 0;           
	int position        = 0;			
	int position_next   = 0;			
	bool isHaveNextNode = false;	  
	while (position < text.length())
	{
		if (isHaveNextNode)
		{
			strNode = text.substr(position_next, 1);
		}
		else
		{
			strNode = text.substr(position, 1);
		}

		tempNode = tempNode->getSubNode(strNode);
		if (nullptr == tempNode) 
		{ 
			if (isHaveNextNode)    
			{
				if (position_next == text.length() - 1)
				{
					result.append(replacement);
					position++;
					beginIndex = position;
				}
				else                                   
				{
					result.append(replacement);
					position++;
					position_next  = position;
					beginIndex     = position;
					tempNode       = rootNode; 
					isHaveNextNode = false;
				}
			}
			else
			{
				result.append(text.substr(beginIndex, 1));
				position_next  = beginIndex + 1;
				position       = position_next;
				beginIndex	   = position;
				tempNode       = rootNode;
				isHaveNextNode = false;
			}
		}
		else if (tempNode->isKeywordEnd())           
		{
			textErrLevel |= tempNode->isKeywordEnd();
			if (textErrLevel <= 1)  
			{
				if (!isHaveNextNode)
				{
					position++;
				}
					position_next++;
			}
			else
			{
				if (tempNode->hasChildren())
				{
					position = position_next;   
					position_next++;
					isHaveNextNode = true;
				}
				else
				{
					result.append(replacement);
					position_next++;
					position   = position_next;
					beginIndex = position;
					tempNode   = rootNode;    
					isHaveNextNode = false;
				}
			}
		}
		else										 
		{
			if (!isHaveNextNode)
			{
				position++;
			}
				position_next++;
		}
	}
	result.append(text.substr(beginIndex));
	return result;
}

当中国为敏感词时 源文本为中&&国匹配不上 该功能暂未完成
在这里插入图片描述

代码下载

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值