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;
}
当中国为敏感词时 源文本为中&&国匹配不上 该功能暂未完成