首页 技术 正文
技术 2022年11月14日
0 收藏 335 点赞 4,545 浏览 4461 个字

这个是好几年前写的了.都统一放到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));

}
}

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,088
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,564
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,413
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,186
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,822
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,905