using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace ConsoleAppTest
{
class Program
{
/// <summary>
/// 简单关键字过滤
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
var ss = CheckDirtyWords("sswo1lfsss殺殺殺喫屎阿三大蘇打阿薩大大愛的愛的大量加拉傑拉德拉薩大家安靜杜拉斯的就拉客的就拉省的家裏卡等級了及案例記錄記錄加拉多久啦結束了");
Console.WriteLine(ss);
Console.ReadLine();
} /// <summary>
/// 检查指定的内容是否包含非法关键字
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
protected static bool CheckDirtyWords(string text)
{
var dirtyStr = "wolf|jason|hoho|barry|喫屎";
if (string.IsNullOrEmpty(dirtyStr))
{
return false;
}
List<string> keywords = dirtyStr.Split('|').ToList();
KeywordFilter ks = new KeywordFilter(keywords);
return ks.FindAllKeywords(text).Count > ;
}
} /// <summary>
/// Aho-Corasick算法实现
/// </summary>
public class KeywordFilter
{
/// <summary>
/// 构造节点
/// </summary>
private class Node
{
private Dictionary<char, Node> transDict; public Node(char c, Node parent)
{
this.Char = c;
this.Parent = parent;
this.Transitions = new List<Node>();
this.Results = new List<string>(); this.transDict = new Dictionary<char, Node>();
} public char Char
{
get;
private set;
} public Node Parent
{
get;
private set;
} public Node Failure
{
get;
set;
} public List<Node> Transitions
{
get;
private set;
} public List<string> Results
{
get;
private set;
} public void AddResult(string result)
{
if (!Results.Contains(result))
{
Results.Add(result);
}
} public void AddTransition(Node node)
{
this.transDict.Add(node.Char, node);
this.Transitions = this.transDict.Values.ToList();
} public Node GetTransition(char c)
{
Node node;
if (this.transDict.TryGetValue(c, out node))
{
return node;
} return null;
} public bool ContainsTransition(char c)
{
return GetTransition(c) != null;
}
} private Node root; // 根节点
private string[] keywords; // 所有关键词 public KeywordFilter(IEnumerable<string> keywords)
{
this.keywords = keywords.ToArray();
this.Initialize();
} /// <summary>
/// 根据关键词来初始化所有节点
/// </summary>
private void Initialize()
{
this.root = new Node(' ', null); // 添加模式
foreach (string k in this.keywords)
{
Node n = this.root;
foreach (char c in k)
{
Node temp = null;
foreach (Node tnode in n.Transitions)
{
if (tnode.Char == c)
{
temp = tnode; break;
}
} if (temp == null)
{
temp = new Node(c, n);
n.AddTransition(temp);
}
n = temp;
}
n.AddResult(k);
} // 第一层失败指向根节点
List<Node> nodes = new List<Node>();
foreach (Node node in this.root.Transitions)
{
// 失败指向root
node.Failure = this.root;
foreach (Node trans in node.Transitions)
{
nodes.Add(trans);
}
}
// 其它节点 BFS
while (nodes.Count != )
{
List<Node> newNodes = new List<Node>();
foreach (Node nd in nodes)
{
Node r = nd.Parent.Failure;
char c = nd.Char; while (r != null && !r.ContainsTransition(c))
{
r = r.Failure;
} if (r == null)
{
// 失败指向root
nd.Failure = this.root;
}
else
{
nd.Failure = r.GetTransition(c);
foreach (string result in nd.Failure.Results)
{
nd.AddResult(result);
}
} foreach (Node child in nd.Transitions)
{
newNodes.Add(child);
}
}
nodes = newNodes;
}
// 根节点的失败指向自己
this.root.Failure = this.root;
} /// <summary>
/// 找出所有出现过的关键词
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
public List<KeywordSearchResult> FindAllKeywords(string text)
{
List<KeywordSearchResult> list = new List<KeywordSearchResult>(); Node current = this.root;
for (int index = ; index < text.Length; ++index)
{
Node trans;
do
{
trans = current.GetTransition(text[index]); if (current == this.root)
break; if (trans == null)
{
current = current.Failure;
}
} while (trans == null); if (trans != null)
{
current = trans;
} foreach (string s in current.Results)
{
list.Add(new KeywordSearchResult(index - s.Length + , s));
}
} return list;
} /// <summary>
/// 简单地过虑关键词
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
public string FilterKeywords(string text)
{
StringBuilder sb = new StringBuilder(); Node current = this.root;
for (int index = ; index < text.Length; index++)
{
Node trans;
do
{
trans = current.GetTransition(text[index]); if (current == this.root)
break; if (trans == null)
{
current = current.Failure;
} } while (trans == null); if (trans != null)
{
current = trans;
} // 处理字符
if (current.Results.Count > )
{
string first = current.Results[];
sb.Remove(sb.Length - first.Length + , first.Length - );// 把匹配到的替换为**
sb.Append(new string('*', current.Results[].Length)); }
else
{
sb.Append(text[index]);
}
} return sb.ToString();
}
} /// <summary>
/// 表示一个查找结果
/// </summary>
public struct KeywordSearchResult
{
private int index;
private string keyword;
public static readonly KeywordSearchResult Empty = new KeywordSearchResult(-, string.Empty); public KeywordSearchResult(int index, string keyword)
{
this.index = index;
this.keyword = keyword;
} /// <summary>
/// 位置
/// </summary>
public int Index
{
get { return index; }
} /// <summary>
/// 关键词
/// </summary>
public string Keyword
{
get { return keyword; }
}
}
}

Aho-Corasick算法实现(简单关键字过滤)的更多相关文章

  1. 多模字符串匹配算法-Aho–Corasick

    背景 在做实际工作中,最简单也最常用的一种自然语言处理方法就是关键词匹配,例如我们要对n条文本进行过滤,那本身是一个过滤词表的,通常进行过滤的代码如下 for (String document : d ...

  2. Aho - Corasick string matching algorithm

    Aho - Corasick string matching algorithm 俗称:多模式匹配算法,它是对 Knuth - Morris - pratt algorithm (单模式匹配算法) 形 ...

  3. 冒泡排序算法和简单选择排序算法的js实现

    之前已经介绍过冒泡排序算法和简单选择排序算法和原理,现在有Js实现. 冒泡排序算法 let dat=[5, 8, 10, 3, 2, 18, 17, 9]; function bubbleSort(d ...

  4. 短链接及关键字过滤ac自动机设计思路

    =============:短链接设计思路:核心:将长字符转为短字符串并建立映射关系,存储redis中.1.使用crc32转换为Long 2.hashids将long encode为最短字符串.作为短 ...

  5. 机器学习&数据挖掘笔记(常见面试之机器学习算法思想简单梳理)

    机器学习&数据挖掘笔记_16(常见面试之机器学习算法思想简单梳理) 作者:tornadomeet 出处:http://www.cnblogs.com/tornadomeet 前言: 找工作时( ...

  6. 使用C语言实现二维,三维绘图算法(3)-简单的二维分形

    使用C语言实现二维,三维绘图算法(3)-简单的二维分形 ---- 引言---- 每次使用OpenGL或DirectX写三维程序的时候, 都有一种隔靴搔痒的感觉, 对于内部的三维算法的实现不甚了解. 其 ...

  7. [转]机器学习&数据挖掘笔记_16(常见面试之机器学习算法思想简单梳理)

    机器学习&数据挖掘笔记_16(常见面试之机器学习算法思想简单梳理) 转自http://www.cnblogs.com/tornadomeet/p/3395593.html 前言: 找工作时(I ...

  8. 1101: 零起点学算法08——简单的输入和计算(a+b)

    1101: 零起点学算法08--简单的输入和计算(a+b) Time Limit: 1 Sec  Memory Limit: 128 MB   64bit IO Format: %lldSubmitt ...

  9. java程序员到底该不该了解一点算法(一个简单的递归计算斐波那契数列的案例说明算法对程序的重要性)

    为什么说 “算法是程序的灵魂这句话一点也不为过”,递归计算斐波那契数列的第50项是多少? 方案一:只是单纯的使用递归,递归的那个方法被执行了250多亿次,耗时1分钟还要多. 方案二:用一个map去存储 ...

随机推荐

  1. Go语言程序开发初涉

    由于工作原因,现在开始学习Go语言.这也是本人第一篇关于Go的博客.本文将通过一些基本概念的说明和实际案例,使得大家能快速对Go程序的开发有个了解. 一. Go的安装 :     在 https:// ...

  2. 设计模式C++学习笔记之七(AbstractFactory抽象工厂模式)

      抽象工厂,提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类.对于工厂方法来说,抽象工厂可实现一系列产品的生产,抽象工厂更注重产品的组合. 看代码: 7.1.解释 main(),女 ...

  3. u3d发送邮件

    http://gad.qq.com/article/detail/22810 https://www.douban.com/note/655356118/ http://gad.qq.com/arti ...

  4. cu命令

    选项: -b:仅显示行中指定直接范围的内容: -c:仅显示行中指定范围的字符: -d:指定字段的分隔符,默认的字段分隔符为“TAB”: -f:显示指定字段的内容: -n:与“-b”选项连用,不分割多字 ...

  5. VS2017打包C#桌面应用

    原文地址:https://blog.csdn.net/houheshuai/article/details/78518097 在要打包项目的解决方案 右键→添加→ 新建项目 后出现如下选择 如果没有V ...

  6. JUnit3 和 JUnit4的区别

    JUnit3 和 JUnit4的区别 1.JUnit 4使用org.junit.*包而JUnit 3.8使用的是junit.Framework.*;为了向后兼容,JUnit4发行版中加入了这两种包. ...

  7. HNU 2015暑期新队员训练赛2 B Combination

    先转化出求 Cnr中有多少奇数 其实就是 (n 的二进制数中 1 的个数为 k ,则这个奇数为 2 ^ k) 因为数很大, 故要快速求出区间的奇数 然后求 0 – low-1 的奇数, 0- high ...

  8. Ex3_7无向图二部图_十一次作业

    (a) 从图中的某个顶点做深度优先遍历,并将不同层的顶点标记为红黑两种颜色,使得每条树边的两个顶点的颜色都不相同,如果遇到一条回边并且两个顶点的颜色都相同则说明图不是二部图. (b)如果存在一个长度为 ...

  9. [JavaScript]使用ArrayBuffer和Blob编辑二进制流

    Blob()构造方法返回一个新的Blob对象. 内容是包含参数array的二进制字节流. 语法 var aBlob = new Blob( array, options ); 参数 array is ...

  10. 自定义session,cookie

    第一种情况:没有设置缓存:执行相对应的setitem等方法进行,保存到字典里面 cookies_dic={}print(cookies_dic)class Session(): def __init_ ...