AC自动机

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);
        }
    }

}
相关文章
相关标签/搜索