我如何从python中的一组单词中寻找最短的唯一子序列?

时间:2014-03-18 00:57:45

标签: string algorithm python-3.3

如果我有一组类似的词,例如:

\bigoplus
\bigotimes
\bigskip
\bigsqcup
\biguplus
\bigvee
\bigwedge
...
\zebra
\zeta 

我想找到最独特的一组字母,这些字母可以唯一地表征每个单词 即。

\bigop:
     \bigoplus
\bigot:
     \bigotimes
\bigsk:
     \bigskip

编辑:注意唯一的序列标识符始终从单词的开头开始。我正在编写一个应用程序,在打字时提供代码段建议。因此,一般来说,用户将从单词

的开头开始输入

等等,序列只需要足以唯一地表征一个单词。 编辑:但需要从这个词的开头开始。 表征始终从单词的开头开始。 我的想法: 我正在考虑对单词进行排序,并根据第一个字母字母进行分组,然后可能使用最长的常见子序列算法来找到最常见的子序列,取其长度并使用长度+ 1个字符表示该唯一子字符串,但我卡住了因为我知道最长子序列的算法通常一次只能采用两个参数,并且每个组中可能有两个以上的单词以特定的字母开头。 我在解决一个已经解决过的探针?谷歌没有帮助。

2 个答案:

答案 0 :(得分:3)

我假设您要找到唯一标识字符串的前缀,因为如果您可以选择任何子序列,那么例如 om 就足够了在您的示例中识别 \ bigotimes

您可以利用这样的事实:对于给定的单词,具有最长公共前缀的单词将按字典顺序与其相邻。 由于您的字典似乎已经被排序,您可以通过找到消除其邻居歧义的最长前缀来找出每个单词的解决方案。

示例:

>>> lst = r"""
... \bigoplus
... \bigotimes
... \bigskip
... \bigsqcup
... \biguplus
... \bigvee
... \bigwedge
... """.split()
>>> lst.sort()      # necessary if lst is not already sorted
>>> lst = [""] + lst + [""]
>>> def cp(x): return len(os.path.commonprefix(x))
... 
>>> { lst[i]: 1 + max(cp(lst[i-1:i+1]), cp(lst[i:i+2])) for i in range(1,len(lst)-1) }
{'\\bigvee': 5, 
 '\\bigsqcup': 6, 
 '\\biguplus': 5, 
 '\\bigwedge': 5, 
 '\\bigotimes': 6, 
 '\\bigoplus': 6, 
 '\\bigskip': 6}

数字表示单词的最小唯一标识前缀的长度。

答案 1 :(得分:0)

以为我会把它放在这里,因为它与我要问的问题最相似:

寻找更好的解决方案(当我找到一个时会报告)迭代一系列字符串,尝试将最短唯一字符串映射到/。

例如,按以下顺序:

['blue', 'black', 'bold']
# 'blu' --> 'blue'
# 'bla' --> 'black'
# 'bo'  --> 'bold'

希望改进我的第一个微弱的解决方案。这就是我想出的:

# Note: Iterating through the keys in a dict, mapping shortest 
#       unique string to the original string.
shortest_unique_strings = {}
for k in mydict:
    for ix in range(len(k)):
        # When the list-comp only has one item.
        # 'key[:ix+1]' == the current substring
        if len([key for key in mydict if key.startswith(key[:ix+1])]) == 1:
            shortest_unique_strings[key[:ix+1]] = k
            break

注意:在提高效率方面:我们应该能够删除已找到的那些键/字符串,以便连续搜索不必重复这些项目。

注意:我特意避免在内置函数之外创建/使用任何函数。