java实现多模匹配算法
这个是好几年前写的了.都统一放到cnblogs上面.
--------------------------------Node ----------------------------------
package com;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @desc ac节点
* @date 2012-08-04
*
*/
public class Node {
private Map<String, Node> sons = new HashMap<String, Node>();
// 指向失败链
private Node fail;
private Node parent;
// 输出标志
private boolean out;
// 字符
private String val;
public void addSon(String val, Node son) {
sons.put(val, son);
}
public Map<String, Node> getSons() {
return sons;
}
public Node getFail() {
return fail;
}
public void setFail(Node fail) {
this.fail = fail;
}
public Node getParent() {
return parent;
}
public void setParent(Node parent) {
this.parent = parent;
}
public boolean isOut() {
return out;
}
public void setOut(boolean out) {
this.out = out;
}
public String getVal() {
return val;
}
public void setVal(String val) {
this.val = val;
}
public String toString() {
List<String> result = new ArrayList<String>();
result.add(this.getVal());
Node parent = this.getParent();
while (parent != null) {
result.add(parent.getVal());
parent = parent.getParent();
}
StringBuffer res = new StringBuffer();
for (int i = result.size() - 1; i >= 0; i--) {
res.append(result.get(i));
}
return res.toString();
}
}
-------------------------------------------------------------SearchTree --------------------------------
package com;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.sohu.fortune.talk.admin.util.ac.Node;
/**
* @desc 查找树
*
* AC 多模匹配 分为三步
* 1. 字典树的构造,
* 按照关键志生成一个查找树.
* 2.失败链的构造,
* 最大后缀表示,生成查找失败节点的下一跳(和kmp模式匹配差不多)
* 3.输出
*
*/
public class SearchTree {
// 跟节点
private Node root = new Node();
// 生成fail,遍历用
private List<String> keywords = new ArrayList<String>();
/**
* 添加关键词,生成一个查找树
*
* 1. 字典树的构造
* @param keyword
*/
public void add(String keyword) {
if (keyword == null || keyword.length() == 0) {
return;
}
keywords.add(keyword);
Node currNode = root;
for (int i = 0, j = keyword.length(); i < j; i++) {
char c = keyword.charAt(i);
String value = String.valueOf(c);
if (currNode.getSons().containsKey(value)) {
Node selectNode = currNode.getSons().get(value);
if (i == j - 1) {
selectNode.setOut(true);
}
currNode = selectNode;
} else {
Node sNode = new Node();
sNode.setVal(value);
sNode.setParent(currNode);
currNode.addSon(value, sNode);
if (i == j - 1) {
sNode.setOut(true);
}
currNode = sNode;
}
}
}
/**
* 失败链的构造
*/
public void buildFail() {
root.setFail(root);
for (String keyword : keywords) {
// 最大后缀表示
Node fail = root;
String prefix = "";
for (char c : keyword.toCharArray()) {
prefix += c;
Node currNode = searchNode(prefix);
String sval = String.valueOf(c);
if (fail.getSons().containsKey(sval)) {
if (fail.getSons().get(sval) != currNode) {
fail = fail.getSons().get(sval);
currNode.setFail(fail);
} else {
fail = root;
currNode.setFail(fail);
}
} else {
// 查找后缀,匹配最大
boolean hasfound = false;
for (int i = 1; i < prefix.length(); i++) {
String suffix = prefix.substring(i);
Node sufNode = searchNode(suffix);
if (sufNode != null) {
currNode.setFail(sufNode);
fail = sufNode;
hasfound = true;
break;
}
}
if (!hasfound) {
currNode.setFail(root);
fail = root;
}
}
}
}
}
/**
* 根据字符串 查找node
*
* @param keyword
* @return
*/
private Node searchNode(String keyword) {
if (keyword.length() == 1) {
return root.getSons().get(keyword);
} else {
Node tree = root.getSons().get(keyword.substring(0, 1));
for (int i = 1, j = keyword.length(); i < j; i++) {
char c = keyword.charAt(i);
String value = String.valueOf(c);
if (tree != null) {
if (tree.getSons().containsKey(value)) {
tree = tree.getSons().get(value);
} else {
return null;
}
} else {
return null;
}
}
return tree;
}
}
// 查找关键词
public Set<String> search(String exp, Set<String> levelSet) {
Node pathNode = root;
for (int i = 0, j = exp.length(); i < j; i++) {
char c = exp.charAt(i);
String value = String.valueOf(c);
if (pathNode.getSons().containsKey(value)) {
pathNode = pathNode.getSons().get(value);
if (pathNode.isOut()) {
levelSet.add("[" + pathNode.toString() + "]");
}
} else {
do {
if (pathNode.isOut()) {
if (pathNode.isOut()) {
levelSet.add("[" + pathNode.toString() + "]");
}
}
if (pathNode.getSons().containsKey(value)) {
pathNode = pathNode.getSons().get(value);
if (pathNode.isOut()) {
levelSet.add("[" + pathNode.toString() + "]");
}
break;
}
} while ((pathNode = pathNode.getFail()) != root);
if (pathNode == root) {
if (pathNode.getSons().containsKey(value)) {
pathNode = pathNode.getSons().get(value);
if (pathNode.isOut()) {
levelSet.add("[" + pathNode.toString() + "]");
}
}
}
}
}
return levelSet;
}
public Node getRoot() {
return root;
}
public static void main(String args[]) {
SearchTree tree = new SearchTree();
tree.add("ai.aaa");
tree.add("美国");
tree.add("ai.oa");
tree.add("ai.vcv5");
tree.add(".org");
// tree.add("baid.us");
tree.buildFail();
//
Set<String> res = new HashSet<String>();
System.out
.print(tree
.search(
"用来ai.aaa自美ai.aaa国ai.aaa的页岩.org气革命打压大秦不成立:1、中国埋藏3000米左右,远大于美国1000米;2、西煤东运2020年之前留有3500万吨缺口;3、美国的天然气发电成本低而我国高且缺少资源;4、美国2015年前不是停止发电使用煤,而是采取了碳发电新技术即煤气化发电;5、我国的电力需求总体上是增长趋势。",
res));
}
}
java实现多模匹配算法的更多相关文章
- 基于AC有限状态机的多模匹配算法
参考链接:http://www.cnblogs.com/zzqcn/p/3525636.html 感谢原文作者. 花了两天半时间实现并测试了算法. 按照上文的思路实现了一遍,可能是原文中有些地方描述的 ...
- 多模匹配算法之Aho-Corasick
除剔除那些含有敏感词的文本,由于有大量的敏感词,所以通过简单的正则表达式和字符串查找的方式效率太低,每次都有遍历一次字符串.而AC算法的核心思想就是避免不必要的回溯使搜索一直沿着向前的方向,最大可能的 ...
- Aho-Corasick算法、多模正则匹配、Snort入门学习
希望解决的问题 . 在一些高流量.高IO的WAF中,是如何对规则库(POST.GET)中的字符串进行多正则匹配的,是单条轮询执行,还是多模式并发执行 . Snort是怎么组织.匹配高达上千条的正则规则 ...
- AC多模式匹配算法
建议:学习ac算法最好的途径是看论文pdf_Efficient_String_Matching_An_Aid_to_Biblio 一.一般的搜索算法 keyword: { he, she, his, ...
- 【模式匹配】Aho-Corasick自动机
1. 多模匹配 AC自动机(Aho-Corasick Automaton)是多模匹配算法的一种.所谓多模匹配,是指在字符串匹配中,模式串有多个.前面所介绍的KMP.BM为单模匹配,即模式串只有一个.假 ...
- Mysql Index、B Tree、B+ Tree、SQL Optimization
catalog . 引言 . Mysql索引 . Mysql B/B+ Tree . Mysql SQL Optimization . MySQL Query Execution Process 1. ...
- AC自动机(转)
http://www.cppblog.com/mythit/archive/2009/04/21/80633.html 首先简要介绍一下AC自动机:Aho-Corasick automation,该算 ...
- AC自动机算法详解
首先简要介绍一下AC自动机:Aho-Corasick automation,该算法在1975年产生于贝尔实验室,是著名的多模匹配算法之一.一个常见的例子就是给出n个单词,再给出一段包含m个字符的文章, ...
- AC自动机算法详解 (转载)
首先简要介绍一下AC自动机:Aho-Corasick automation,该算法在1975年产生于贝尔实验室,是著名的多模匹配算法之一.一个常见的例子就是给出n个单词,再给出一段包含m个字符的文章, ...
随机推荐
- Metadata Lock原理5
[MySQL] 之一2015-09-05 15:46:51 分类: MySQL 一 简介 和MySQL打交道比较多的朋友,肯定遇到过 "Waiting for table metadata ...
- java_DAO类基本设计
package cn.itcast.oa.base; import java.util.List; public interface BaseDao<T> { void save(T en ...
- Java设计模式14:常用设计模式之组合模式(结构型模式)
http://blog.csdn.net/jason0539/article/details/22642281
- javascript的变量、作用域和内存问题
基本类型和引用类型的值执行环境垃圾收集 ECMAScript 变量可能包含两种不同数据类型的值:基本类型值和引用类型值.基本类型值指的是简单的数据段引用类型值指那些可能由多个值构成的对象 基本数据类型 ...
- RMI学习
前段时间学习JMX,知道可以使用rmi连接器,就顺便看下rmi是什么东西,RMI 全称Remote Method Invocation-远程方法调用,实现远程对象之间的调用,下面原理图来自网络 服务器 ...
- 命名管道FIFO
首先我得检讨一下自己,这几天有些颓呀,打不起精神,板子出了点问题,果真自学还是很困难呀,硬件方面难解决呀,理想与现实还是很有差距的,伤透了,凌乱了. 一直在理解进程间通信的问题.发现上次忽略了一个问题 ...
- MVC清除缓存设置+数据验证
[OutputCache(Location = OutputCacheLocation.None, NoStore = true)] [Table("User")]:定义UserD ...
- Linux 命令 - alias: 设置或显示别名
当一个命令太长或者不符合用户的习惯,那么可以为该命令指定一个符合用户习惯的别名.比如习惯 DOS 命令的用户可以使用 alias md='mkdir' 命令将 md 来替换 mkdir.有时也为经常调 ...
- Linux C编程--格式化I/O
printf(格式控制,输入表列) 例:printf("%d%d",a,b) (1)d格式符:输出一个有符号的十进制整数 (2)c格式符:输出一个字符 (3)s格式符:输出一个字符 ...
- 【转】Android 布局学习之——LinearLayout属性baselineAligned的作用及baseline
相信大家对LinearLayout已经相当熟悉,但你们是否了解它的属性baselineAligned呢? Android官方文档是这么描述的: