DFA算法

DFA全称为:Deterministic Finite Automaton,即确定有穷自动机。其特征为:有一个有限状态集合和一些从一个状态通向另一个状态的边,每条边上标记有一个符号,其中一个状态是初态,某些状态是终态。但不同于不确定的有限自动机,DFA中不会有从同一状态出发的两条边标志有相同的符号。

简单点说就是,它是通过event和当前的state得到下一个state,即event+state=nextstate。理解为系统中有多个节点,通过传递进入的event,来确定走哪个路由至另一个节点,而节点是有限的。

关键字提取的DFA算法

以“工人阶级”和“工农联盟”两个关键词来进行描述,首先构建关键词库,这个词二叉树构造为:

构造成HashMap:

{
    "工": {
        "isEnd": false,
        "人": {
            "isEnd": false,
            "阶": {
                "isEnd": false,
                "级": {
                    "isEnd": true,
                    "label": "工人阶级"
                }
            }
        },
        "农": {
            "isEnd": false,
            "联": {
                "isEnd": false,
                "盟": {
                    "isEnd": true,
                    "label": "工农联盟"
                }
            }
        }
    }
}

代码实现

构造关键词

/**
 * 标签集进行哈希映射
 *
 * @param labels
 * @return
 */
public static Map<String, Map> labelsToHashMap(Set<String> labels) {
    Map<String, Map> labelHashMap = new HashMap<String, Map>(labels.size());

    // 当前映射
    Map currentMap = null;

    // 标签名称
    String label;

    // 循环标签集
    Iterator<String> labelIterator = labels.iterator();
    while (labelIterator.hasNext()) {
        label = labelIterator.next();
        currentMap = labelHashMap;
        // 循环关键字
        for (int i = 0; i < label.length(); i++) {
            // 关键词的每一个单字
            char word = label.charAt(i);

            // 关键字的映射是否存在
            boolean exist = currentMap.containsKey(word);
            // 如果关键字不存在映射中,将关键字存在映射中
            if (!exist) {
                Map newWordMap = new HashMap<String, Boolean>();
                newWordMap.put("isEnd", false); // 不是最后一个元素
                currentMap.put(word, newWordMap);
                currentMap = newWordMap;
            }
            // 如果关键字存在映射中,获取该映射
            else {
                currentMap = (Map) currentMap.get(word);
            }

            // 如果该关键字是该关键词的最后一个字,标记为关键词结束
            if (i == label.length() - 1) {
                currentMap.put("isEnd", true);
                currentMap.put("label", label);
            }
        }
    }

    return labelHashMap;
}

匹配关键词

/**
 * 解析文本内容,抽取标签
 *
 * @param content
 * @return
 */
public static Map<String, Integer> parse(String content, Map<String, Map> labelMap) {

    Map<String, Integer> labels = new HashMap<String, Integer>();

    // 按字符循环文本内容
    for (int i = 0; i < content.length(); i++) {
        // 文本字符
        char word = content.charAt(i);
        // 关键字是否存在
        boolean exist = labelMap.containsKey(word);
        // 关键字存在
        if (exist) {
            // 字符指针
            int j = i;
            // 获得关键字映射
            Map map = labelMap.get(word);
            // 关键词是否结束
            boolean isEnd = (boolean) map.get("isEnd");
            // 关键词词结束
            if (isEnd) {
                // 获得关键词计数
                int num = labels.getOrDefault(map.get("label"), 0);
                // 更新关键词计数
                labels.put((String) map.get("label"), num + 1);
            }
            // 关键词未结束
            while (!isEnd || map.size() > 2) {
                // 获得下一个文本字符
                char nextWord = ' ';
                if (++j < content.length()){
                    nextWord = content.charAt(j);
                }
                // 下一个文本字符是否是关键词
                boolean existNext = map.containsKey(nextWord);
                // 下一个字是关键字
                if (existNext) {
                    // 获得下一个关键字的映射
                    map = (Map) map.get(nextWord);
                    isEnd = (boolean) map.get("isEnd");
                    if (isEnd) {
                        // 获得关键词计数
                        int num = labels.getOrDefault(map.get("label"), 0);
                        // 更新关键词计数
                        labels.put((String) map.get("label"), num + 1);
                    }
                }
                // 下一个字不是关键字
                else {
                    break;
                }
            }
            // end of while loop
        }
        // 关键字不存在
        else {
            continue;
        }
    }
    return labels;
}

results matching ""

    No results matching ""