这个是好几年前写的了.都统一放到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实现多模匹配算法的更多相关文章

  1. 基于AC有限状态机的多模匹配算法

    参考链接:http://www.cnblogs.com/zzqcn/p/3525636.html 感谢原文作者. 花了两天半时间实现并测试了算法. 按照上文的思路实现了一遍,可能是原文中有些地方描述的 ...

  2. 多模匹配算法之Aho-Corasick

    除剔除那些含有敏感词的文本,由于有大量的敏感词,所以通过简单的正则表达式和字符串查找的方式效率太低,每次都有遍历一次字符串.而AC算法的核心思想就是避免不必要的回溯使搜索一直沿着向前的方向,最大可能的 ...

  3. Aho-Corasick算法、多模正则匹配、Snort入门学习

    希望解决的问题 . 在一些高流量.高IO的WAF中,是如何对规则库(POST.GET)中的字符串进行多正则匹配的,是单条轮询执行,还是多模式并发执行 . Snort是怎么组织.匹配高达上千条的正则规则 ...

  4. AC多模式匹配算法

    建议:学习ac算法最好的途径是看论文pdf_Efficient_String_Matching_An_Aid_to_Biblio 一.一般的搜索算法 keyword: { he, she, his, ...

  5. 【模式匹配】Aho-Corasick自动机

    1. 多模匹配 AC自动机(Aho-Corasick Automaton)是多模匹配算法的一种.所谓多模匹配,是指在字符串匹配中,模式串有多个.前面所介绍的KMP.BM为单模匹配,即模式串只有一个.假 ...

  6. Mysql Index、B Tree、B+ Tree、SQL Optimization

    catalog . 引言 . Mysql索引 . Mysql B/B+ Tree . Mysql SQL Optimization . MySQL Query Execution Process 1. ...

  7. AC自动机(转)

    http://www.cppblog.com/mythit/archive/2009/04/21/80633.html 首先简要介绍一下AC自动机:Aho-Corasick automation,该算 ...

  8. AC自动机算法详解

    首先简要介绍一下AC自动机:Aho-Corasick automation,该算法在1975年产生于贝尔实验室,是著名的多模匹配算法之一.一个常见的例子就是给出n个单词,再给出一段包含m个字符的文章, ...

  9. AC自动机算法详解 (转载)

    首先简要介绍一下AC自动机:Aho-Corasick automation,该算法在1975年产生于贝尔实验室,是著名的多模匹配算法之一.一个常见的例子就是给出n个单词,再给出一段包含m个字符的文章, ...

随机推荐

  1. centos x86_64--------------------------------系统调用

    http://blog.csdn.net/hmsiwtv/article/details/11022241 [root@monitor ~]# cat /usr/include/asm/unistd. ...

  2. 关于删除linux多余内核

    step 1: 查找当前正在使用的内核文件的版本号 #uname -r step 2: 列出所有的内核文件,使用rpm 或者 dpkg(基于linux系统) 命令  #rpm -q kernel 或者 ...

  3. cocos2d-x lua与c++简单交互

    cocos2d-x lua与c++简单交互 version: cocos2d-x 3.6 本文讲述lua与c++的一些简单交互: lua通过消息方式调用c++无参接口 c++调用lua带参接口 1.通 ...

  4. U盘安装Debian 7

    网上看到好多使用U盘安装的教程,齐说不一.实践是检验真理的标准,Try it ! 下载系统镜像:http://cdimage.debian.org/cdimage/release/current/am ...

  5. Codeforces Round 190 div.2 322C 321A Ciel and Robot

    唔...这题是数学题. 比赛时做出来,但题意理解错了,以为只要判断那点是不是在线上就行了,发现过不了样例就没提交. 思路:记录每一步的偏移,假设那点是在路径上的某步,然后回推出那一个周期的第一步,判断 ...

  6. gulp构建工具的安装

    第一步:node.js安装 在gulp安装之前,本机需要node环境.访问http://nodejs.org,然后点击大大的绿色的install按钮,下载完成后直接运行程序.npm会随着安装包一起安装 ...

  7. 在vs中跑动kdtree 和 bbf

    这两天的学习模型都来自:http://blog.csdn.net/masibuaa/article/details/9246493 所谓的bbf 英文名字叫做best bin first 译名:最优节 ...

  8. linux 文件夹权限及umask

    先创建一个目录,看看权限: $ ll 总用量 drwxrwxr-x huangxm huangxm 2月 : ./ drwxr-xr-x huangxm huangxm 2月 : ../ drwxrw ...

  9. Linux下文件的三个时间(Atime,Mtime,Ctime)

    文件的三个时间 我们已经很熟悉windows系统了,那么我们在windows下新建一个文件,我们知道它在保存的时候肯定是会保存一下文件的创建时间之类的信息的,那么我们来看看windows下的一个文件保 ...

  10. C++函数学习笔记

    C++继承了C语言的全部语法,也包括函数的定义和使用方法. 调用其他函数的函数因为位高权重被尊称为主调函数,被其他函数调用的函数称为被调函数. 函数的返回值由return语句给出,return 表达式 ...