当前位置 : 主页 > 网络推广 > seo >

基本分词

来源:互联网 收集:自由互联 发布时间:2021-06-16
中文分词有很多算法,同时大都是基于四种基本的分词方式,在基本的分词基础上做一些歧义消除、未登录词识别等功能。 下面以“南京市长江大桥”为例,分享一下四种基本的分词

中文分词有很多算法,同时大都是基于四种基本的分词方式,在基本的分词基础上做一些歧义消除、未登录词识别等功能。

下面以“南京市长江大桥”为例,分享一下四种基本的分词

正向最大匹配

从字面就很好理解,就是一句话从头开始读,可着最长的词取。

// 南京市长江大桥 --> 南京市 长江大桥

代码

List<Word> segmentation(String text) {
        Queue<Word> results = new LinkedList<>();
        int textLength = text.length();
        // 设置词的最大长度,词库中最长词的长度跟目标句子长度中,取最小
        int wordMaxLength = min(DictionaryFactory.getDictionary().getMaxWordLength(), textLength);
        int start = 0; // 开始分词的位置

        while (start < textLength) {
            int currentLength = min(textLength - start, wordMaxLength); // 未分词的句子长度
            boolean isSeg = false;
            while (start + currentLength <= textLength) {
                if (DictionaryFactory.getDictionary().contains(text, start, currentLength)) {
                    addWord(results, text, start, currentLength); // 成功分词  加入results中
                    isSeg = true;
                    break;
                } else if (--currentLength <= 0) { // 剩余长度为0 跳出当前循环
                    break;
                }
            }

            if (isSeg) {
                start += currentLength;
            } else {
                addWord(results, text, start++, 1); // 没有分出词  单字成词
            }
        }

        return new ArrayList<>(results);
    }

结果

正向最小匹配

跟上边的正好形成对比,这个也是正向,但是是可着最小的词先分

// 南京市长江大桥 --> 南京 市长 江 大桥

代码

List<Word> segmentation(String text) {
        Queue<Word> results = new LinkedList<>();
        int textLength = text.length();
        int wordMinLength = 2; //最小词长 这里不考虑单字的词
        int start = 0;

        while (start < textLength) {
            int currentLength = wordMinLength; // 从start处开始 从长度为2开始查找可分的词
            boolean isSeg = false;
            while (start + currentLength <= textLength) {
                if (DictionaryFactory.getDictionary().contains(text, start, currentLength)) {
                    addWord(results, text, start, currentLength);
                    isSeg = true;
                    break;
                } else if (++currentLength > DictionaryFactory.getDictionary().getMaxWordLength()) { // 没有的话就让currentLength+1,如果大于词典中最长的词就跳出循环
                    break;
                }
            }

            if (isSeg) {
                start += currentLength;
            } else {
                addWord(results, text, start++, 1);
            }
        }

        return new ArrayList<>(results);
    }

结果

逆向最大匹配

也是可着最大的词先分,不过是从后往前开始分

// 南京市长江大桥 --> 南京市 长江大桥

代码

public List<Word> segmentation(String text) {
        Deque<Word> results = new ArrayDeque<>();
        int wordMaxLength = min(DictionaryFactory.getDictionary().getMaxWordLength(), text.length());
        int end = text.length();

        while (end > 0) {
            int currentLength = min(wordMaxLength, end);
            boolean isSeg = false;
            while (end - currentLength >= 0) {
                if (DictionaryFactory.getDictionary().contains(text, end - currentLength, currentLength)) {
                    addWord(results, text, end - currentLength, currentLength);
                    isSeg = true;
                    break;
                } else if (--currentLength <= 0) {
                    break;
                }
            }

            if (isSeg) {
                end -= currentLength;
            } else {
                addWord(results, text, --end, 1);
            }
        }

        return new ArrayList<>(results);
    }

结果

逆向最小匹配

正向最小匹配倒过来即可

// 南京市长江大桥 --> 南京市 长江 大桥

代码

public List<Word> segmentation(String text) {
        Deque<Word> results = new ArrayDeque<>();
        int wordMinLength = 2;
        int end = text.length();

        while (end > 0) {
            int currentLength = wordMinLength;
            boolean isSeg = false;
            while (end - currentLength >= 0) {
                if (DictionaryFactory.getDictionary().contains(text, end - currentLength, currentLength)) {
                    addWord(results, text, end - currentLength, currentLength);
                    isSeg = true;
                    break;
                } else if (++currentLength > DictionaryFactory.getDictionary().getMaxWordLength()) {
                    break;
                }
            }

            if (isSeg) {
                end -= currentLength;
            } else {
                addWord(results, text, --end, 1);
            }
        }

        return new ArrayList<>(results);
    }

结果

网友评论