【问题标题】:Checking if word segmentation is possible检查是否可以分词
【发布时间】:2012-05-03 14:02:15
【问题描述】:

这是对this response 和用户发布的伪代码算法的后续问题。由于它的年龄,我没有对这个问题发表评论。我只对验证字符串是否可以拆分为单词感兴趣。该算法不需要实际拆分字符串。这是来自链接问题的回复:

让 S[1..length(w)] 是一个带有布尔条目的表。 S[i] 为真,如果 单词 w[1..i] 可以拆分。然后设置 S[1] = isWord(w[1]) 并为 i=2 到 length(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 是否仅由单词组成?在这种情况下,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

【问题讨论】:

  • 你有没有让这个工作?
  • @thinkdevcode 是的。请参阅我对accepted answer 的评论。

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


【解决方案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 的整个字符串由一个字典单词组成
  • 或者存在带有j<i 的S[j-1]==true,并且字符串[j:i] 是单个字典词

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

【讨论】:

  • 我更新了我的问题,因为算法仍然没有返回正确的解决方案。
【解决方案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

【讨论】:

  • 感谢您的帮助。该代码有效。我更正了您打印语句中的错误(缺少结尾 ],所以最后一行看起来像这样:print(S[len(a_string)-1]))并添加了我自己的常用字典函数,它看起来正在工作。
【解决方案3】:

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

使用pip 可以轻松安装:

$ pip install wordsegment

segment 返回一个单词列表:

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

【讨论】:

  • 嗨@GrantJ,我正在使用你的python包word segment。太棒了。尽管它适用于仅涉及文本的文本,但一旦文本中出现数字,它就不会按预期工作。例如,以下文本:joined the habit in 2008, after karpreilly, a private investment 变为 ['joined', 'the', 'habit', 'in2008afterkarp', 'reilly', 'a', 'private', 'investment']。当涉及数字时,您知道是否有解决问题的方法吗?谢谢
  • 不确定。你能打开一个 GitHub 问题吗?
猜你喜欢
  • 2019-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-28
  • 2017-02-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多