package com.chipmunk.algorithm.trie; public class Branch { private char word; private byte status = 0;//0词语未结束1词语结束 private Branch[] branches = null; public Branch(char word) { super(); this.word = word; } public Branch(char word, byte status) { super(); this.word = word; this.status = status; } /** * * @param b * @return */ public Branch add(Branch b){ if (branches==null) { branches=new Branch[1]; branches[0] = b; return branches[0]; }else { char w1=b.getWord(); //判断是否已经有相等的字 int i = -1; for (int j = 0; j < branches.length; j++) { Branch bb =branches[j]; char w2 = bb.getWord(); if (w1==w2) { i=j; //如果原来这个字不是结束符,更改为结束符 if (b.getStatus()==1&&bb.getStatus()==0) { bb.setStatus(b.getStatus()); } break; } } if (i>-1) {//字已经添加过了 return branches[i]; }else {//添加一个字 Branch[]branches2=new Branch[branches.length+1]; System.arraycopy(branches,0,branches2,0,branches.length); branches2[branches2.length-1]=b; branches=branches2; return branches[branches.length-1]; } } } public char getWord() { return word; } public void setWord(char word) { this.word = word; } public byte getStatus() { return status; } public void setStatus(byte status) { this.status = status; } public Branch[] getBranches() { return branches; } public void setBranches(Branch[] branches) { this.branches = branches; } }
package com.chipmunk.algorithm.trie; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; public class TrieTree { /** * 向trie树添加新词 * @param root * @param text */ private static void addWords(Branch root,String text){ Branch branch_grow = root; char[] chars = text.toCharArray(); for (int i = 0; i < chars.length; i++) { byte status = 0; if (i == chars.length-1) { status = 1; } Branch b = branch_grow.add(new Branch(chars[i], status)); branch_grow=b; } } /** * 搜索一个词---全匹配 * @param root 树根 * @param text 搜索词 * @return */ private static boolean searchTerm(Branch root,String text){ char[]cs = text.toCharArray(); Branch finder = root; for (int i = 0; i < cs.length; i++) { char c = cs[i]; boolean bool_equal = false; boolean bool_last = i==cs.length-1;//最后一个字 Branch[]bs = finder.getBranches(); if (bs!=null) { for (Branch branch : bs) { char w = branch.getWord(); if (c==w) { finder=branch; if (bool_last) { byte status = branch.getStatus(); if (status==0) {//是否是词语最后一个字 bool_equal = false; }else { bool_equal = true; } }else { bool_equal = true; } break; } } } if (!bool_equal) { return false; } } return true; } /** * 搜索一个词---部分匹配 * @param root 树根 * @param text 搜索词 * @return */ public static List<String> searchTermPart(Branch root,String text){ char[]cs = text.toCharArray(); List<String> list = new ArrayList<String>(); StringBuffer text_temp = new StringBuffer(); Branch finder = root; for (int i = 0; i < cs.length; i++) { char c = cs[i]; boolean bool_equal = false;//是否相等 Branch[]bs = finder.getBranches(); if (bs!=null) { for (Branch branch : bs) { char w = branch.getWord(); if (c==w) { finder=branch; byte status = branch.getStatus(); text_temp.append(c); // System.out.println(status+"--"+c); if (status==1) {//词语结尾标示 list.add(text_temp.toString()); } bool_equal = true; break; } } } if (!bool_equal&&text_temp.length()>0) { return list; } } return list; } public static List<String> searchAllTerms(Branch root,String text){ char[]cs = text.toCharArray(); List<String> list = new ArrayList<String>(); StringBuffer text_temp = new StringBuffer(); Branch finder = root; for (int i = 0; i < cs.length; i++) { // System.out.println(i); char c = cs[i]; boolean bool_equal = false;//是否相等 Branch[]bs = finder.getBranches(); if (bs!=null) { for (Branch branch : bs) { char w = branch.getWord(); if (c==w) { finder=branch; byte status = branch.getStatus(); text_temp.append(c); // System.out.println(status+"--"+c+"--"+i); if (status==1) { list.add(text_temp.toString()); } bool_equal = true; break; } } } //到了不等的文字节点 if (!bool_equal&&text_temp.length()>0) { i=i-text_temp.length(); text_temp=new StringBuffer();//临时匹配文字组归零 finder=root;//文字查找器回trie树根部 } } return list; } /** * 种树--建立trie树 * @param words * @return */ public static Branch plantTree(Collection<String> words){ Branch root = new Branch(' '); for (String w : words) { addWords(root, w); } return root; } /** * 打印所有树枝字 * @param tree */ public static void print(Branch tree){ Branch[] bs = tree.getBranches(); if (bs!=null) { for (Branch branch : bs) { System.out.print(branch.getWord()); if (branch.getStatus()==1) { System.out.println(); } print(branch); } } } public static void main(String[] args) { List<String> words = new ArrayList<String>(); words.add("中国人"); words.add("中华民族"); words.add("中华"); words.add("大中华区"); words.add("中华人民共和国"); words.add("中华民国"); words.add("华人"); words.add("国歌"); Branch tree = plantTree(words); System.out.println(searchTerm(tree, "中华人民共和国")); System.out.println(searchAllTerms(tree, "唱中华人民共和国国歌是")); // 01234 56789 10 // print(tree); } }
相关推荐
- 在AC自动机中,Trie树被用于模式匹配,能够高效地处理多个模式的匹配问题。 #### Trie树的时间与空间复杂度分析 - **时间复杂度**:插入、查找的时间复杂度均为O(N),其中N为字符串长度。 - **空间复杂度**:在...
AC自动机的核心思想是将所有模式串构建为一棵树,这棵树被称为“失败链接树”或“AC树”。在AC树中,每个节点对应一个前缀字符串,从根节点到某个节点的路径上的边代表了路径上所有节点对应的字符串连接。当在输入...
AC自动机在Trie树的基础上进行了扩展,增加了失败指针,以实现更快速的匹配过程。 首先,我们需要理解Trie树,也被称为前缀树或字典树。Trie树是一种用于存储字符串集合的数据结构,每个节点代表一个前缀,从根节点...
AC自动机的核心在于构建一个trie树(字典树),并将失败指针(failure link)添加到树中。Trie树是一种特殊的树形结构,用于存储一个字符集合中的所有字符串。在AC自动机中,每个节点代表一个前缀字符串,而边则表示...
- **时间复杂度**:构建关键词树的时间复杂度为O(n),构建整个AC自动机的时间复杂度也为O(n)。 #### 四、AC自动机的核心组件 1. **goto函数g(q,a)** - 定义:给出当前状态q和输入字符a,返回从状态q出发沿着值为...
要学AC自动机需要自备两个前置技能:KMP和trie树(其实个人感觉不会kmp也行,失配指针的概念并不难) 其中,KMP是用于一对一的字符串匹配,而trie虽然能用于多模式匹配,但是每次匹配失败都需要进行回溯,如果模式串很长的话...
### AC自动机与Aho-Corasick算法 #### 一、引言 在计算机科学领域,文本搜索是一项基本且重要的任务。AC自动机(Aho-Corasick Algorithm)是一种高效解决多个模式匹配问题的经典算法。它能在一个目标文本中同时查找...
AC自动机是在Trie树的基础上扩展,增加两个关键功能:失败指针(failure function)和发射函数(emits function)。失败指针用于在匹配失败时,迅速找到下一个可能匹配的位置;发射函数则记录当前节点对应的模式串,...
AC自动机基于字典树(Trie)的概念,并对其进行扩展,以实现快速的多模式匹配。字典树可以存储一个字符串集合,每个节点代表一个前缀,叶子节点代表一个完整字符串。AC自动机在字典树的基础上添加了“失败指针”...
本文将深入探讨四种重要的字符串处理技术:哈希(Hash)、KMP算法、Trie树(字典树)以及AC自动机。这些都是在解决字符串匹配问题时常用的方法,它们各有优缺点,适用于不同的场景。 1. **哈希(Hash)**: 哈希是...
AC自动机的核心思想是将所有待匹配的模式字符串构建为一个特殊的树形结构—— Failure Function(失败函数)或Failure Link(失败链接)。这个结构允许我们在遇到不匹配字符时,快速地跳转到下一个可能匹配的位置,...
接下来,我们将深入探讨AC自动机的工作原理、实现方法以及它与字典树的关系。 **AC自动机的基本概念** AC自动机是由Aho和Corasick在1975年提出的,它的核心思想是构建一个状态机,每个状态代表一个或多个字符串,...
- 在Python2环境下,可以使用字典数据结构来表示Trie树,使用递归或迭代的方法计算失败指针,并通过遍历文本和AC自动机的节点进行匹配。 - `automaton.py` 文件很可能包含了上述步骤的具体代码实现,包括Trie树...
AC自动机通过构建一个Trie树(字典树或前缀树)并进行优化,使得可以在O(m+n)的时间复杂度内查找模式串集合中的所有子串在主串中出现的位置,其中m是模式串的总长度,n是主串的长度。 首先,我们需要理解Trie树的...
**AC自动机(Aho-Corasick算法)**是一种高效的字符串搜索算法,它基于字典树(Trie)数据结构,能够一次性查找多个模式串在文本中的出现情况。AC自动机的主要优势在于避免了对同一个文本位置多次进行模式匹配,大大...
**AC自动机(Aho-Corasick Algorithm)模板** AC自动机是一种字符串搜索算法,它在文本中查找多个模式串的出现情况。该算法由艾伦·科拉斯和戈登·科拉斯在1975年提出,是KMP算法和后缀自动机的结合,具有高效性和...
AC自动机结合了字典树(Trie树)和KMP算法的思想。它通过预处理阶段构建一个自动机,该自动机包含了所有模式串的信息,从而能够在主文本中高效地进行匹配。 ##### 字典树(Trie树) - **定义**:字典树是一种特殊...
在给定的标题和描述中,提到了几种不同的字符串匹配方法:KMP算法、AC自动机与Trie树以及后缀数组。接下来,我们将详细讨论这些算法。 1. **KMP算法**: KMP(Knuth-Morris-Pratt)算法是一种高效的单串匹配算法,...
AC自动机算法的实现。...要搞懂AC自动机,先得有模式树(字典树)Trie和KMP模式匹配算法的基础知识。AC自动机算法分为3步:构造一棵Trie树,构造失败指针和模式匹配过程。本资源简单实现了这些功能。
AC自动机的核心思想是构建一个包含所有模式的字典树(也称为 Failure Function 或 Trie),并在这个字典树中添加失败指针。这使得在搜索过程中,当当前字符匹配失败时,可以快速地跳转到下一个可能匹配的位置,而...