检查是否可以进行分词

时间:2012-04-22 21:49:47

标签: python algorithm nlp dynamic-programming text-segmentation

这是this response的后续问题以及用户发布的伪代码算法。由于它的年龄,我没有对这个问题发表评论。我只想验证一个字符串是否可以拆分成单词。该算法不需要实际拆分字符串。这是相关问题的回复:

  

设S [1..length(w)]是具有布尔条目的表。如果,S [i]是真的   w [1..i]这个词可以分开。然后设置S [1] = isWord(w [1])并为   i = 2到长度(w)计算

     

S [i] =(isWord [w [1..i]或{2..i}中的任何j:S [j-1]和   isWord [j..i])。

我正在将这个算法翻译成简单的python代码,但我不确定我是否正确理解它。代码:

def is_all_words(a_string, dictionary)):
    str_len = len(a_string)
    S = [False] * str_len
    S[0] = is_word(a_string[0], dictionary)
    for i in range(1, str_len):
        check = is_word(a_string[0:i], dictionary)
        if (check):
            S[i] = check
        else:
            for j in range(1, str_len):
                check = (S[j - 1] and is_word(a_string[j:i]), dictionary)
                if (check):
                    S[i] == True
                    break
    return S

我有两个相关的问题。 1)此代码是否是链接算法到Python的正确翻译,如果是,2)现在我有S,我如何使用它来判断字符串是否只包含单词 ?在这种情况下,is_word是一个简单地在列表中查找给定单词的函数。我还没有实现它作为特里。

更新:更新代码以包含建议的更改后,它不起作用。这是更新的代码:

def is_all_words(a_string, dictionary)):
    str_len = len(a_string)
    S = [False] * str_len
    S[0] = is_word(a_string[0], dictionary)
    for i in range(1, str_len):
        check = is_word(a_string[0:i], dictionary)
        if (check):
            S[i] = check
        else:
            for j in range(1, i): #THIS LINE WAS UPDATED
                check = (S[j - 1] and is_word(a_string[j:i]), dictionary)
                if (check):
                    S[i] == True
                    break
    return S

a_string = "carrotforever"
S = is_all_words(a_string, dictionary)
print(S[len(S) - 1]) #prints FALSE

a_string = "hello"
S = is_all_words(a_string, dictionary)
print(S[len(S) - 1]) #prints TRUE

它们应该返回True这两个。

3 个答案:

答案 0 :(得分:2)

以下是代码的修改版本,应返回良好的结果。 请注意,您的错误只是从伪代码数组索引(从1开始)到python数组索引(从0开始)的转换,因此S [0]和S [1]填充了相同的值,其中S [L-1]实际上从未计算过。您可以通过打印整个S值轻松跟踪此错误。你会发现S [3]在第一个例子中设置为true,它应该是单词“car”的S [2]。 此外,您可以通过存储到目前为止找到的复合词的索引来加速该过程,而不是测试每个位置。

def is_all_words(a_string, dictionary):
    str_len = len(a_string)
    S = [False] * (str_len)
# I replaced is_word function by a simple list lookup, 
# feel free to replace it with whatever function you use. 
# tries or suffix tree are best for this.
    S[0] = (a_string[0] in dictionary) 
    for i in range(1, str_len):
        check = a_string[0:i+1] in dictionary # i+1 instead of i
        if (check):
            S[i] = check
    else:
        for j in range(0,i+1): # i+1 instead of i
            if (S[j-1] and (a_string[j:i+1] in dictionary)): # i+1 instead of i
            S[i] = True
            break


    return S

a_string = "carrotforever"
S = is_all_words(a_string, ["a","car","carrot","for","eve","forever"])
print(S[len(a_string)-1]) #prints TRUE

a_string = "helloworld"
S = is_all_words(a_string, ["hello","world"])
print(S[len(a_string)-1]) #prints TRUE

答案 1 :(得分:2)

有关如何进行英语分词的实际示例,请查看Python wordsegment module的来源。它有点复杂,因为它使用单词和短语频率表,但它说明了递归方法。通过修改score功能,您可以优先考虑更长的匹配。

使用pip

轻松安装
$ pip install wordsegment

segment会返回一个单词列表:

>>> import wordsegment
>>> wordsegment.segment('carrotfever')
['carrot', 'forever']

答案 2 :(得分:1)

1)乍一看,看起来不错。一件事:for j in range(1, str_len):应该是for j in range(1, i):我认为

2)如果S [str_len-1] == true,则整个字符串应仅由整个单词组成。

毕竟S [i]为真如果

  • 从0到i的整个字符串由单个字典单词
  • 组成
  • 或者{[1}}存在S [j-1] == true,字符串[j:i]是单个字典

所以如果S [str_len-1]为真,则整个字符串由字典单词组成