自动状态机学习及java实现

目录

一、前提

二、java实现(版本1)

1、节点类-ApNode

2、节点帮助类-ApNodeHelper

 3、算法类-AhoPaper

3.1、goto函数-gotoFunc

3.2、fail函数-failFunc

3.3、output生成

3.4、find函数-findFunc

三、java实现(版本2)有限确定自动机

1、moveNext概念

2、构建moveNext-dfaFunc及相关函数

3、加入moveNext的find函数

四、总结

1、算法总结

2、阅读论文总结

3、勘误


一、前提

是学习 Efficient string matching: an aid to bibliographic search  1975年的论文,看了很久,但是很多内容还是没看懂。

这里就其中的一些算法java版本实现及自己的理解记录下。

这个算法是用于文本匹配的,这在搜索中很常用,比如有词根:he、his,输入she,可以解析出he。

二、java实现(版本1)

节点类:

import java.util.List;
import java.util.Map;
import java.util.TreeMap;

public class ApNode {

    private int state;
    private Map<Character, ApNode> go;

    private ApNode fail;

    /**
     * output函数,仅root节点有
     */
    private Map<ApNode, List<String>> output;

    public ApNode() {
        go = new TreeMap<>();
    }

    public int getState() {
        return state;
    }

    public void setState(int state) {
        this.state = state;
    }

    public Map<Character, ApNode> getGo() {
        return go;
    }

    public void setGo(Map<Character, ApNode> go) {
        this.go = go;
    }

    public ApNode getFail() {
        return fail;
    }

    public void setFail(ApNode fail) {
        this.fail = fail;
    }

    public Map<ApNode, List<String>> getOutput() {
        return output;
    }

    public void setOutput(Map<ApNode, List<String>> output) {
        this.output = output;
    }

    @Override
    public String toString() {
        StringBuilder bld = new StringBuilder();
        bld.append(state);
        if (go.size() > 0) {
            bld.append("->");
        }
        for (Map.Entry<Character, ApNode> entry : go.entrySet()) {
            bld.append("\n\t");
            bld.append(entry.getKey());
            bld.append(":");
            String value = entry.getValue().toString();
            for (int i = 0; i < value.length(); i++) {
                char c = value.charAt(i);
                bld.append(c);
                if (i != 0 && value.charAt(i - 1) == '\n' && c == '\t') {
                    bld.append('\t');
                }
            }
        }
        return bld.toString();
    }
}

节点帮助类:

import java.util.*;

public class ApNodeHelper {

    public static ApNode goFunc(ApNode root, ApNode state, char a, boolean isCreating) {
        if (state.getGo().containsKey(a)) {
            return state.getGo().get(a);
        }
        if (isCreating) {
            //代表没有通路
            return null;
        }
        //如果是root没有路径的,全部赋值root
        return root == state ? root : null;
    }

    public static String outputFail(ApNode node) {
        StringBuilder noBld = new StringBuilder();
        StringBuilder failBld = new StringBuilder();
        if (node.getState() != 0) {
            noBld.append(node.getState()).append(" ");
            failBld.append(node.getFail().getState()).append(" ");
        }
        LinkedList<ApNode> queue = new LinkedList<>();
        for (ApNode goNode : node.getGo().values()) {
            queue.offer(goNode);
        }

        while (!queue.isEmpty()) {
            ApNode currentNode = queue.poll();
            noBld.append(currentNode.getState()).append(" ");
            failBld.append(currentNode.getFail().getState()).append(" ");
            for (ApNode goNode : currentNode.getGo().values()) {
                queue.offer(goNode);
            }
        }

        noBld.append('\n');
        noBld.append(failBld);
        return noBld.toString();
    }

    public static void output(ApNode root) {
        for (Map.Entry<ApNode, List<String>> entry : root.getOutput().entrySet()) {
            System.out.println(entry.getKey().getState() + ":" + Arrays.toString(entry.getValue().toArray()));
        }
    }

    public static void addOutput(Map<ApNode, List<String>> output, ApNode c, List<String> keywords) {
        if (keywords == null || keywords.size() == 0) {
            return;
        }
        List<String> emits = output.get(c);
        if (emits == null) {
            ArrayList<String> newEmits = new ArrayList<>();
            newEmits.addAll(keywords);
            output.put(c, newEmits);
        } else {
            for (int i = 0; i < keywords.size(); i++) {
                if (!emits.contains(keywords.get(i))) {
                    emits.add(keywords.get(i));
                }
            }
        }

    }

    public static void addOutput(Map<ApNode, List<String>> output, ApNode c, String keyword) {
        List<String> emits = output.get(c);
        if (emits == null) {
            ArrayList<String> newEmits = new ArrayList<>();
            newEmits.add(keyword);
            output.put(c, newEmits);
        } else if (!emits.contains(keyword)) {
            emits.add(keyword);
        }
    }
}

算法实现类:

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

public class AhoPaper {

    public static ApNode gotoFunc(ApNode root, AtomicInteger newStateNo, String keyword) {
        if (keyword == null || keyword.length() == 0) {
            return root;
        }
        char[] text = keyword.toCharArray();

        ApNode state = root;
        int j = 0;
        char a;
        while (true) {
            a = text[j];
            ApNode goState = ApNodeHelper.goFunc(root, state, a, true);
            if (goState == null) {
                break;
            }
            state = goState;
            j++;
        }

        for (int p = j; p < text.length; p++) {
            a = text[p];

            ApNode newState = new ApNode();
            newState.setState(newStateNo.incrementAndGet());
            state.getGo().put(a, newState);

            state = newState;
        }
        ApNodeHelper.addOutput(root.getOutput(), state, keyword);

        return state;
    }

    public static void failFunc(ApNode root) {
        LinkedList<ApNode> queue = new LinkedList<>();

        //第一层
        for (ApNode node : root.getGo().values()) {
            node.setFail(root);
            queue.offer(node);
        }

        //剩余层
        while (!queue.isEmpty()) {
            ApNode parentNode = queue.poll();
            for (Map.Entry<Character, ApNode> entry : parentNode.getGo().entrySet()) {
                char a = entry.getKey();
                ApNode currentNode = entry.getValue();
                queue.offer(currentNode);

                ApNode state = parentNode.getFail();
                while (true) {
                    ApNode goState = ApNodeHelper.goFunc(root, state, a, false);
                    if (goState !=
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值