package com.oooo3d.trie;
import java.util.ArrayList;
import java.util.List;
/**
* 树的最大匹配
*
* @author bob
* @创建时间:2013-1-30上午11:33:42
* @version 2.0
*/
public class TrieTree
{
/**
* 根节点,不存储数据
*/
private TrieNode root = new TrieNode("`");
/**
* 查找数据
*
* @param data
* @return
*/
public boolean find(String data)
{
TrieNode firstChild = root.firstChild();
if (firstChild == null)
{
return false;
}
TrieNode node = find(firstChild, data);
return node != null ? node.exists() : false;
}
/**
* 插入数据
*
* @param data
* @return
*/
public void insert(String data)
{
TrieNode firstChild = root.firstChild();
if (firstChild == null)
{
root.firstChild(new TrieNode(data, true));
}
else
{
insert(firstChild, data);
}
}
/**
* 删除数据
*
* @param node
* @param data
*/
public void delete(String data)
{
TrieNode firstChild = root.firstChild();
if (firstChild == null)
{
return;
}
TrieNode node = find(firstChild, data);
if (node != null)
{
node.exists(false);
}
}
/**
* 匹配数据
* @param data
* @return
*/
public List<String> searchData(String data)
{
List<String> list = new ArrayList<String>();
TrieNode firstChild = root.firstChild();
if (firstChild != null)
{
TrieNode node = searchFuzzyWord(firstChild, data);
if (node != null)
{
pathes(node, list, new StringBuilder(data));
}
}
return list;
}
/**
* 从指定节点开始插入数据
*
* @param node
* @param data
* @return
*/
private void insert(TrieNode node, String data)
{
String value = node.value();
if (data.equals(value))
{
// 插入数据存在
node.exists(true);
{
return;
}
}
int index = maxLenth(data, value);
if (index == 0)
{
// 没有公共开始部分,将数据插入兄弟节点
TrieNode brother = node.nextBrother();
if (brother != null)
{
insert(brother, data);
}
else
{
node.nextBrother(new TrieNode(data, true));
}
}
else
{
if (value.length() > index)
{
// 节点数据多于公共部分,则节点进行纵向分裂
// 将多余部分插入孩子节点
TrieNode temp = new TrieNode(value.substring(index),
node.exists());
TrieNode child = node.firstChild();
// 将原节点的孩子节点变为孙子节点
if (child != null)
{
temp.firstChild(child);
}
// 原节点的数据更新为公共部分
node.value(value.substring(0, index));
// 公共部分是否为插入数据
node.exists(node.value().equals(data));
node.firstChild(temp);
}
if (data.length() > index)
{
// 插入数据多于公共部分,则多余部分插入孩子节点
TrieNode firstChild = node.firstChild();
if (firstChild == null)
{
// 如果没有孩子节点,则创建孩子节点
node.firstChild(new TrieNode(data.substring(index), true));
}
else
{
// 否则直接插入孩子节点
insert(firstChild, data.substring(index));
}
}
}
}
/**
* 从指定节点开始查找数据
*
* @param node
* @param data
*/
private TrieNode find(TrieNode node, String data)
{
String value = node.value();
if (data.equals(value))
{
// 查询数据存在
return node;
}
int index = maxLenth(data, value);
if (index == 0)
{
// 不存在公共部分,查询兄弟节点
TrieNode brother = node.nextBrother();
return brother != null ? find(brother, data) : null;
}
TrieNode firstChild = node.firstChild();
// 节点数据为查询数据的前缀,则继续查询子节点
return data.startsWith(value) && firstChild != null ? find(firstChild,
data.substring(value.length())) : null;
}
/**
* 两个字符串公共开始部分的长度
* @param str1
* @param str2
* @return
*/
private static int maxLenth(String str1, String str2)
{
int len = str1.length() < str2.length() ? str1.length() : str2.length();
int index = -1;
for (int i = 0; i < len; i++)
{
if (str1.charAt(i) != str2.charAt(i))
break;
index = i;
}
return index + 1;
}
/**
* <模糊匹配>
* 比如存在主题词,中华人民共和国,当输入中华或者中华人民,都可以匹配到该词
* 但如果存在两个主题词中华人民共和国和中华,输入中华时,应该匹配到中华
* 而输入中华人民时应该匹配到中华人民共和国,满足正向最大匹配需要
*
* @param node
* node
* @return String String
* @see [类、类#方法、类#成员]
*/
private TrieNode searchFuzzyWord(TrieNode node, String data)
{
String value = node.value();
if (value.startsWith(data))
{
TrieNode temp = new TrieNode(value.substring(data.length()));
temp.firstChild(node.firstChild);
temp.exists(node.exists() && !temp.value().isEmpty());
return temp;
}
int index = maxLenth(data, value);
if (index == 0)
{
// 不存在公共部分,查询兄弟节点
TrieNode brother = node.nextBrother();
return brother != null ? searchFuzzyWord(brother, data) : null;
}
TrieNode firstChild = node.firstChild();
// 节点数据为查询数据的前缀,则继续查询子节点
return data.startsWith(value) && firstChild != null ? searchFuzzyWord(
firstChild,
data.substring(value.length())) : null;
}
/**
* 获取指定节点存在的全部子路径
*
* @param node
* @param list
* @param sb
*/
private void pathes(TrieNode node, List<String> list, StringBuilder sb)
{
sb.append(node.value());
if (node.exists())
{
// 将匹配到的都放到集合中
list.add(sb.toString());
}
else
{
// 如果全量匹配到则结束匹配
list.add(sb.toString());
return;
}
if (node.firstChild() != null)
{
pathes(node.firstChild(), list, sb);
}
sb.delete(sb.length() - node.value().length(), sb.length());
if (node.nextBrother() != null)
{
pathes(node.nextBrother(), list, sb);
}
}
public static void main(String[] args)
{
TrieTree t = new TrieTree();
String str = "中国";
String str1 = "中国人民";
String str2 = "中国人民共和国";
t.insert(str);
t.insert(str1);
t.insert(str2);
List<String> list = t.searchData("中国人");
System.out.println(list);
}
}
package com.oooo3d.trie;
/**
*
* @author bob
* @创建时间:2013-1-30下午01:29:11
* @version 2.0
*/
public class TrieNode
{
/**
* 当前节点数据
*/
private String value;
/**
* 第一个子节点
*/
public TrieNode firstChild;
/**
* 下一个节点
*/
private TrieNode nextBrother;
/**
* 节点数据存在标志
*/
private boolean exists= true;
/**
* 构造方法
*
* @param value
* 节点数据
*/
public TrieNode(String value)
{
this(value, true);
}
/**
* 构造方法
*
* @param value
* 节点数据
* @param exists
* 节点数据是否存在
*/
public TrieNode(String value, boolean exists)
{
this.value = value;
this.exists = exists;
}
/**
* 节点数据
*
* @return
*/
public String value()
{
return value;
}
/**
* 设置节点数据
*
* @param value
*/
public void value(String value)
{
this.value = value;
}
public boolean exists()
{
return exists;
}
public void exists(boolean exists)
{
this.exists = exists;
}
public TrieNode firstChild()
{
return firstChild;
}
public void firstChild(TrieNode node)
{
this.firstChild = node;
}
public TrieNode nextBrother()
{
return nextBrother;
}
public void nextBrother(TrieNode node)
{
this.nextBrother = node;
}
public String toString()
{
return value + "[" + exists + "]";
}
}
import java.util.ArrayList;
import java.util.List;
/**
* 树的最大匹配
*
* @author bob
* @创建时间:2013-1-30上午11:33:42
* @version 2.0
*/
public class TrieTree
{
/**
* 根节点,不存储数据
*/
private TrieNode root = new TrieNode("`");
/**
* 查找数据
*
* @param data
* @return
*/
public boolean find(String data)
{
TrieNode firstChild = root.firstChild();
if (firstChild == null)
{
return false;
}
TrieNode node = find(firstChild, data);
return node != null ? node.exists() : false;
}
/**
* 插入数据
*
* @param data
* @return
*/
public void insert(String data)
{
TrieNode firstChild = root.firstChild();
if (firstChild == null)
{
root.firstChild(new TrieNode(data, true));
}
else
{
insert(firstChild, data);
}
}
/**
* 删除数据
*
* @param node
* @param data
*/
public void delete(String data)
{
TrieNode firstChild = root.firstChild();
if (firstChild == null)
{
return;
}
TrieNode node = find(firstChild, data);
if (node != null)
{
node.exists(false);
}
}
/**
* 匹配数据
* @param data
* @return
*/
public List<String> searchData(String data)
{
List<String> list = new ArrayList<String>();
TrieNode firstChild = root.firstChild();
if (firstChild != null)
{
TrieNode node = searchFuzzyWord(firstChild, data);
if (node != null)
{
pathes(node, list, new StringBuilder(data));
}
}
return list;
}
/**
* 从指定节点开始插入数据
*
* @param node
* @param data
* @return
*/
private void insert(TrieNode node, String data)
{
String value = node.value();
if (data.equals(value))
{
// 插入数据存在
node.exists(true);
{
return;
}
}
int index = maxLenth(data, value);
if (index == 0)
{
// 没有公共开始部分,将数据插入兄弟节点
TrieNode brother = node.nextBrother();
if (brother != null)
{
insert(brother, data);
}
else
{
node.nextBrother(new TrieNode(data, true));
}
}
else
{
if (value.length() > index)
{
// 节点数据多于公共部分,则节点进行纵向分裂
// 将多余部分插入孩子节点
TrieNode temp = new TrieNode(value.substring(index),
node.exists());
TrieNode child = node.firstChild();
// 将原节点的孩子节点变为孙子节点
if (child != null)
{
temp.firstChild(child);
}
// 原节点的数据更新为公共部分
node.value(value.substring(0, index));
// 公共部分是否为插入数据
node.exists(node.value().equals(data));
node.firstChild(temp);
}
if (data.length() > index)
{
// 插入数据多于公共部分,则多余部分插入孩子节点
TrieNode firstChild = node.firstChild();
if (firstChild == null)
{
// 如果没有孩子节点,则创建孩子节点
node.firstChild(new TrieNode(data.substring(index), true));
}
else
{
// 否则直接插入孩子节点
insert(firstChild, data.substring(index));
}
}
}
}
/**
* 从指定节点开始查找数据
*
* @param node
* @param data
*/
private TrieNode find(TrieNode node, String data)
{
String value = node.value();
if (data.equals(value))
{
// 查询数据存在
return node;
}
int index = maxLenth(data, value);
if (index == 0)
{
// 不存在公共部分,查询兄弟节点
TrieNode brother = node.nextBrother();
return brother != null ? find(brother, data) : null;
}
TrieNode firstChild = node.firstChild();
// 节点数据为查询数据的前缀,则继续查询子节点
return data.startsWith(value) && firstChild != null ? find(firstChild,
data.substring(value.length())) : null;
}
/**
* 两个字符串公共开始部分的长度
* @param str1
* @param str2
* @return
*/
private static int maxLenth(String str1, String str2)
{
int len = str1.length() < str2.length() ? str1.length() : str2.length();
int index = -1;
for (int i = 0; i < len; i++)
{
if (str1.charAt(i) != str2.charAt(i))
break;
index = i;
}
return index + 1;
}
/**
* <模糊匹配>
* 比如存在主题词,中华人民共和国,当输入中华或者中华人民,都可以匹配到该词
* 但如果存在两个主题词中华人民共和国和中华,输入中华时,应该匹配到中华
* 而输入中华人民时应该匹配到中华人民共和国,满足正向最大匹配需要
*
* @param node
* node
* @return String String
* @see [类、类#方法、类#成员]
*/
private TrieNode searchFuzzyWord(TrieNode node, String data)
{
String value = node.value();
if (value.startsWith(data))
{
TrieNode temp = new TrieNode(value.substring(data.length()));
temp.firstChild(node.firstChild);
temp.exists(node.exists() && !temp.value().isEmpty());
return temp;
}
int index = maxLenth(data, value);
if (index == 0)
{
// 不存在公共部分,查询兄弟节点
TrieNode brother = node.nextBrother();
return brother != null ? searchFuzzyWord(brother, data) : null;
}
TrieNode firstChild = node.firstChild();
// 节点数据为查询数据的前缀,则继续查询子节点
return data.startsWith(value) && firstChild != null ? searchFuzzyWord(
firstChild,
data.substring(value.length())) : null;
}
/**
* 获取指定节点存在的全部子路径
*
* @param node
* @param list
* @param sb
*/
private void pathes(TrieNode node, List<String> list, StringBuilder sb)
{
sb.append(node.value());
if (node.exists())
{
// 将匹配到的都放到集合中
list.add(sb.toString());
}
else
{
// 如果全量匹配到则结束匹配
list.add(sb.toString());
return;
}
if (node.firstChild() != null)
{
pathes(node.firstChild(), list, sb);
}
sb.delete(sb.length() - node.value().length(), sb.length());
if (node.nextBrother() != null)
{
pathes(node.nextBrother(), list, sb);
}
}
public static void main(String[] args)
{
TrieTree t = new TrieTree();
String str = "中国";
String str1 = "中国人民";
String str2 = "中国人民共和国";
t.insert(str);
t.insert(str1);
t.insert(str2);
List<String> list = t.searchData("中国人");
System.out.println(list);
}
}
package com.oooo3d.trie;
/**
*
* @author bob
* @创建时间:2013-1-30下午01:29:11
* @version 2.0
*/
public class TrieNode
{
/**
* 当前节点数据
*/
private String value;
/**
* 第一个子节点
*/
public TrieNode firstChild;
/**
* 下一个节点
*/
private TrieNode nextBrother;
/**
* 节点数据存在标志
*/
private boolean exists= true;
/**
* 构造方法
*
* @param value
* 节点数据
*/
public TrieNode(String value)
{
this(value, true);
}
/**
* 构造方法
*
* @param value
* 节点数据
* @param exists
* 节点数据是否存在
*/
public TrieNode(String value, boolean exists)
{
this.value = value;
this.exists = exists;
}
/**
* 节点数据
*
* @return
*/
public String value()
{
return value;
}
/**
* 设置节点数据
*
* @param value
*/
public void value(String value)
{
this.value = value;
}
public boolean exists()
{
return exists;
}
public void exists(boolean exists)
{
this.exists = exists;
}
public TrieNode firstChild()
{
return firstChild;
}
public void firstChild(TrieNode node)
{
this.firstChild = node;
}
public TrieNode nextBrother()
{
return nextBrother;
}
public void nextBrother(TrieNode node)
{
this.nextBrother = node;
}
public String toString()
{
return value + "[" + exists + "]";
}
}