参考:https://www.cnblogs.com/kubidemanong/p/10834993.html

public class TreeNode
{
public char Char;
public bool IsEnd;
public int WordEndAt;
private Dictionary<char, TreeNode> NodeDict;
public TreeNode(char c)
{
Char = c;
IsEnd = false;
NodeDict = new Dictionary<char, TreeNode>();
} public bool ContainChar(char ch)
{
return NodeDict.ContainsKey(ch);
} public TreeNode GetChild(char c)
{
TreeNode Child = null;
NodeDict.TryGetValue(c, out Child);
return Child;
} public TreeNode AddNode(char ch)
{
TreeNode insertNode = null;
if (!NodeDict.TryGetValue(ch, out insertNode))
{
insertNode = new TreeNode(ch);
NodeDict.Add(ch, insertNode);
}
return insertNode;
}
}
public class Trie
{ public TreeNode Root { get; }
private HashSet<char> SkipCharSet; //忽略字符
private HashSet<char> SeparateCharSet; //常见分隔符
private string skipCharList = " `-=[]\\',.·/~!@#$%^&*()_+{}|:\"<>?*\r\n";
private TreeNode checkNode;
private TreeNode backupNode;
private char duplicateChar;
public Trie()
{
Root = new TreeNode(' ');
SkipCharSet = new HashSet<char>();
SeparateCharSet = new HashSet<char>();
foreach (char c in skipCharList)
{
SkipCharSet.Add(c);
SeparateCharSet.Add(c);
}
} public void AddNode(TreeNode node, string word)
{
if (word.Length > 0)
{
char ch = word[0];
TreeNode insertNode = node.AddNode(ch);
if (word.Length == 1)
{
insertNode.IsEnd = true;
}
word = word.Remove(0,1);
AddNode(insertNode, word);
}
} private bool IsSkipChar(char c)
{
return SkipCharSet.Contains(c);
} //是否是英文
private bool IsEnglishChar(char ch)
{
string str = new string(ch, 1);
Regex regEnglish = new Regex("^[a-zA-Z]");
return regEnglish.IsMatch(str);
} //是否是分割符
private bool Separator(char ch)
{
return SeparateCharSet.Contains(ch);
} //是否是单词的开头
private bool IsWordBegin(string word,int pos)
{
if (pos == 0)
return true;
if (pos < word.Length)
{
char c1 = word[pos - 1];
char c2 = word[pos];
return (Separator(c1) && !Separator(c2)) || (!IsEnglishChar(c1) && IsEnglishChar(c2));
}
return false;
} //是否是单词的结尾
private bool IsWordEnd(string word,int pos)
{
if (pos == word.Length - 1)
return true;
if(pos < word.Length)
{
char c1 = word[pos];
char c2 = word[pos + 1];
return (!Separator(c1) && Separator(c2)) || (IsEnglishChar(c1) && !IsEnglishChar(c2));
}
return false;
} private void CheckWord(string checkWord,int begin)
{
int index = begin;
while(index + 1 < checkWord.Length)
{
++index;
char ch = checkWord[index];
if (IsSkipChar(ch))
{
if (checkNode.ContainChar(ch))
checkNode = checkNode.GetChild(ch);
}
else
{
if(checkNode.ContainChar(ch))
{
checkNode = checkNode.GetChild(ch);
if(checkNode.IsEnd)
{
checkNode.WordEndAt = index;
backupNode = checkNode;
duplicateChar = ch;
CheckWord(checkWord,index); //继续匹配
break;
}
}
else
{
if (duplicateChar == ch) //屏蔽fuccccccck例如这样的
backupNode.WordEndAt = index;
else
break;
}
}
duplicateChar = ch;
}
} public string Filter(string filterWord)
{
int begin = 0;
checkNode = null;
backupNode = null;
duplicateChar = ' ';
string word = filterWord.ToLower();
StringBuilder result = new StringBuilder(filterWord);
while(begin < word.Length)
{
checkNode = Root;
backupNode = Root;
char ch = word[begin];
duplicateChar = ch;
               //设置是否严格匹配, 即逐个字符检测是否有可能是敏感词,否则像英语一样只检测单词, 
//严格匹配: [av]是敏感词,那么[avoid]被替换成[**oid]
                bool isStrict = !IsEnglishChar(ch);              
                bool isWordBegin = isStrict || IsWordBegin(word, begin);
if(isWordBegin && checkNode.ContainChar(ch))
{
checkNode = checkNode.GetChild(ch);
if(!IsSkipChar(ch))
{
CheckWord(word, begin);
if(backupNode.IsEnd && backupNode.WordEndAt > 0)
{
bool isWordEnd = isStrict || IsWordEnd(word, backupNode.WordEndAt); //到单词末尾才行 have 中有av 但是不是末尾 所以不是屏蔽词
if(isWordEnd)
{
for(int i = begin; i <= backupNode.WordEndAt;++i)
{
result[i] = '*';
}
begin = backupNode.WordEndAt;
}
}
}
}
++begin;
} return result.ToString();
}
}

测试用例:

 class Program
{
static void Main(string[] args)
{
Trie trie = new Trie();
trie.AddNode(trie.Root, "fuc");
trie.AddNode(trie.Root, "fuc bitch");
trie.AddNode(trie.Root, "fuck");
trie.AddNode(trie.Root, "bitch");
trie.AddNode(trie.Root, "屠杀");
Console.WriteLine(trie.Filter("是哦fuckkkkkk山大的撒bi\tch"));
Console.WriteLine(trie.Filter("have world fuc bitch"));
Console.WriteLine(trie.Filter("1218fuck1")); Console.ReadKey();
}
}

结果:

C# 屏蔽词过滤的更多相关文章

  1. Java实现敏感词过滤 - IKAnalyzer中文分词工具

    IKAnalyzer 是一个开源的,基于java语言开发的轻量级的中文分词工具包. 官网: https://code.google.com/archive/p/ik-analyzer/ 本用例借助 I ...

  2. Java实现敏感词过滤 - DFA算法

    Java实现DFA算法进行敏感词过滤 封装工具类如下: 使用前需对敏感词库进行初始化: SensitiveWordUtil.init(sensitiveWordSet); package cn.swf ...

  3. [原创] Trie树 php 实现敏感词过滤

    目录 背景 简介 存储结构 PHP 其他语言 字符串分割 示例代码 php 优化 缓存字典树 常驻服务 参考文章 背景 项目中需要过滤用户发送的聊天文本, 由于敏感词有将近2W条, 如果用 str_r ...

  4. [python每日一练]--0012:敏感词过滤 type2

    题目链接:https://github.com/Show-Me-the-Code/show-me-the-code代码github链接:https://github.com/wjsaya/python ...

  5. java实现敏感词过滤(DFA算法)

    小Alan在最近的开发中遇到了敏感词过滤,便去网上查阅了很多敏感词过滤的资料,在这里也和大家分享一下自己的理解. 敏感词过滤应该是不用给大家过多的解释吧?讲白了就是你在项目中输入某些字(比如输入xxo ...

  6. 用php实现一个敏感词过滤功能

    周末空余时间撸了一个敏感词过滤功能,下边记录下实现过程. 敏感词,一方面是你懂的,另一方面是我们自己可能也要过滤一些人身攻击或者广告信息等,具体词库可以google下,有很多. 过滤敏感词,使用简单的 ...

  7. 浅析敏感词过滤算法(C++)

    为了提高查找效率,这里将敏感词用树形结构存储,每个节点有一个map成员,其映射关系为一个string对应一个TreeNode. STL::map是按照operator<比较判断元素是否相同,以及 ...

  8. Java实现敏感词过滤

    敏感词.文字过滤是一个网站必不可少的功能,如何设计一个好的.高效的过滤算法是非常有必要的.前段时间我一个朋友(马上毕业,接触编程不久)要我帮他看一个文字过滤的东西,它说检索效率非常慢.我把它程序拿过来 ...

  9. php敏感词过滤

    在项目开发中发现有个同事在做敏感词过滤的时候用循环在判断,其实是不用这样做的,用php的数组函数和字符串函数即可实现 function filterNGWords($string) { $badwor ...

  10. 转:鏖战双十一-阿里直播平台面临的技术挑战(webSocket, 敏感词过滤等很不错)

    转自:http://www.infoq.com/cn/articles/alibaba-broadcast-platform-technology-challenges 鏖战双十一-阿里直播平台面临的 ...

随机推荐

  1. About TopoJSON

    An extension of GeoJSON that encodes topology!  TopoJSON https://github.com/topojson/topojson The To ...

  2. Object.create() 方浅析

    Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__. Object.create(proto[, propertiesObject]) 参数 pro ...

  3. IMX6Ull驱动

    mount -t nfs -o nolock,vers=3 192.168.1.117:/home/book/nfs_rootfs /mnt cat /proc/sys/kernel/printk e ...

  4. Vue + Element table的@select方法获取当table中的id值都相同时,获取他们索引

    先说下问题情况,原本通过双重forEach方法方法,遍历可以获取到被勾选中的索引. let arr = []val.forEach((val, index) => { this.TableDat ...

  5. 监听异常:The listener supports no services

    数据库版本:单机环境19c 实例是正常的 [oracle@sit19c admin]$ sqlplus / as sysdba SQL*Plus: Release 19.0.0.0.0 - Produ ...

  6. ELKF搭建

    logstash cat /etc/logstash/logstash.yml |grep -v '#'path.data: /data/logstash/datapipeline.ordered: ...

  7. 《Python 3.8从入门到精通(视频教学版)》PDF电子书赠阅

    <Python 3.8从入门到精通(视频教学版)>PDF电子书赠阅,个人学习使用,禁止任何形式的商用. https://pan.baidu.com/s/1U_8-N9YJVG8UsUHbQ ...

  8. prometheus-alertmanager 告警规则

    # 告警规则参考 https://awesome-prometheus-alerts.grep.to/rules

  9. 解决 django channel: zadd() got an unexpected keyword argument 'daphne.response.HzSXMUhzYL!QSfUgrDObf'

    在stackoverflow上找到答案 If you are using Redis version 3.0 or above, it will not work with channels vers ...

  10. iOS新建项目基础设置

    我们新建项目工程的时候一般都需要配置些基本设置,以下是我整理的一些基础配置 一:  pch文件的设置     pch:预编译头文件,这个文件会被编译存储在一个缓存空间,并自动有且只有一次包含在每个文件 ...