import java.util.*; public class AhoCorasick { private Trie trie; public void buildTrie(String str) { if (trie == null) { trie = new Trie(); } trie.buildTrie(str.toCharArray()); } public void buildFailPointer() { if (trie == null) { trie = new Trie(); } Trie.TrieNode root = trie.getRoot(); root.failPoint = null; Queue<Trie.TrieNode> queue = new LinkedList<>(); queue.offer(root); while (! queue.isEmpty()) { Trie.TrieNode p = queue.poll(); Map<Character, Trie.TrieNode> children = p.children; children.entrySet().forEach(entry -> { Trie.TrieNode pc = entry.getValue(); Trie.TrieNode q = p.failPoint; while (q != null) { Trie.TrieNode qc = q.children.get(entry.getKey()); if (qc != null) { pc.failPoint = qc; break; } q = q.failPoint; } if (q == null) { pc.failPoint = root; } queue.offer(pc); }); } } public void match(String str) { if (str == null || str.length() == 0) { return; } char[] s = str.toCharArray(); Trie.TrieNode p = trie.getRoot(); for (int i = 0; i < s.length; ++ i) { while (p.children.get(s[i]) == null && p != trie.getRoot()) { p = p.failPoint; } p = p.children.get(s[i]); if (p == null) { p = trie.getRoot(); } else { Trie.TrieNode t = p; while (t != trie.getRoot()) { if (t.freq > 0) { System.out.println(String.format("匹配到字符串%s", str.substring(i - t.length + 1, i + 1))); } t = t.failPoint; } } } } public static void main(String[] args) { AhoCorasick ac = new AhoCorasick(); ac.buildTrie("c"); ac.buildTrie("bc"); ac.buildTrie("bcd"); ac.buildTrie("abcd"); ac.buildFailPointer(); Scanner in = new Scanner(System.in); while (in.hasNext()) { String s = in.next(); ac.match(s); } } } class Trie { private TrieNode root; public TrieNode getRoot() { return root; } public void buildTrie(char[] s) { if (s == null || s.length == 0) { return; } TrieNode cur = root; for (int i = 0; i < s.length; ++ i) { TrieNode child = cur.children.get(s[i]); if (child == null) { child = new TrieNode(s[i]); cur.children.put(s[i], child); } child.length = cur.length + 1; cur = child; } cur.freq ++; } public Trie() { this.root = new TrieNode(); } static class TrieNode { char data; int freq; int length; Map<Character, TrieNode> children; TrieNode failPoint; public TrieNode(char data) { this.data = data; this.freq = 0; this.length = 0; this.children = new HashMap<>(0); } public TrieNode() { this.freq = 0; this.length = 0; this.children = new HashMap<>(0); } } }