构建词网时的原子分词问题

3.4.2构建词网

def generate_wordnet(sent, trie):
    """
    生成词网
    :param sent: 句子
    :param trie: 词典(unigram)
    :return: 词网
    """
    searcher = trie.getSearcher(JString(sent), 0)
    wordnet = WordNet(sent)
    while searcher.next():
        wordnet.add(searcher.begin + 1,
                    Vertex(sent[searcher.begin:searcher.begin + searcher.length], searcher.value, searcher.index))
    # 原子分词,保证图连通
    vertexes = wordnet.getVertexes()
    i = 0
    while i < len(vertexes):
        if len(vertexes[i]) == 0:  # 空白行
            j = i + 1
            for j in range(i + 1, len(vertexes) - 1):  # 寻找第一个非空行 j
                if len(vertexes[j]):
                    break
            wordnet.add(i, Vertex.newPunctuationInstance(sent[i - 1: j - 1]))  # 填充[i, j)之间的空白行
            i = j
        else:
            i += len(vertexes[i][-1].realWord)

    return wordnet

作者大大,3.4.2构建词网使用的原子分词那里,为什么在遇到非空行时只处理最后一个单词(比如【和,和服】只处理和服而不关心),这样不会导致部分路径无法到达终点吗?真心求问

代码在做的事情不是遇到非空行取最后一个单词,而是找寻不连通区域的结尾,取不连通区域sent[i - 1: j - 1]作为整个单词

的确部分路径无法到达终点,但这差不多是在这种情况下能做的最佳补救。如果没有任何路径到终点,程序就会死循环,所以我们需要这段代码来将不连通的分量连接起来。而且,这些不连通的区间没有任何子区间出现于词典中,要知道词典收录了几乎所有汉字。这说明这个区间极有可能是英文或数字,所以将其作为一个整体是八成错不了的。当然,Java版本对此作了更精细的区分,就是你在p119看到的那段解释了。

1 Like

明白了,多谢!!!