参考: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. jmeter组件

    1.进程:一个正在执行的程序就对应一个进程 线程:进程中的执行线索(一个进程有多个执行线索) 线程组:按照线程性质对线程进行分组 2.并发执行:多个线程同时执行 特点:执行结束的顺序和线程的启动顺序不 ...

  2. 自定义注解获取请求Header中的值

    前言 这几天开发一个项目,为了方便,前台将当前登陆人的ID和名称放在每个请求的Header中(这里不考虑安全性之类的),这样后台只要需要用到,就直接从Header中get出来就可以了. 后台实现方法 ...

  3. Java基础-类型转换、变量、变量命名规范

    类型转换 强制转换 (类型)变量名 高-->低 自动转换 低-->高 注意点 不能对布尔值进行转换 不能把对象类型转换为不相干的类型 在把高容量转换到低容量的时候,强制转换 转换的时候可能 ...

  4. 1. ansible学习总结: 基础模块

    copy模块: #传输文件到目标机 ansible -i /kingdee/ansible/host all -m copy -a 'src=/tmp/aaaa.tgz dest=/tmp/aaaa. ...

  5. Selenium私房菜系列8 -- 玩转Selenium Server【OO】

    本篇主要是想更进一步介绍Selenium Server的工作原理,这次我们从Selenium Server的交互模式开始. 在<第一个Selenium RC测试案例>中,我们以命令&quo ...

  6. Metasploit渗透测试框架二

    Metasploit基本使用方法 Metasploit基本命令 Metasploit程序需要使用Postgresql数据库. Postgresql是一种特性齐全的自由软件的对象-关系型数据库管理系统( ...

  7. redhat安装opencv2.4.13

    1.官网下载OpenCV2.4.5  http://opencv.org/ 解压到home/用户名/opencv2.4.5 2.安装cmake $sudo apt-get install cmake ...

  8. c语言container_of 编译报错

    求指针ptr所在的结构体实例的首地址, #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) #define co ...

  9. K8S-pod详解

    目录: namespace六大类型 Pod基础概念 Pod两种使用方式 通常把Pod分为两类 Pod容器的分类 init的容器作用 镜像拉取策略(image PullPOlicy) 部署harbor创 ...

  10. vue资料链接

    vue 官方api:https://cn.vuejs.org/ vue资源精选:http://vue.awesometiny.com/ vue GitHub地址:https://github.com/ ...