计算编辑集以将一个字符串转换为另一个字符串的算法?

时间:2016-04-18 15:38:53

标签: python algorithm

我想计算使用插入和删除将一个字符串A转换为另一个字符串B所需的编辑,并且只需要最少的操作数。

像小猫" - > "坐在"会产生一个类似的操作列表("删除0","插入' 0","删除4", "在3","插入''在6")

是否有算法执行此操作,请注意我不想想要编辑距离,我想要实际编辑。

4 个答案:

答案 0 :(得分:1)

我有一个类似于此的任务。尝试使用A *变体。构造一个给定单词的可能“邻居”的图形,并使用A *向外搜索,距离启发式是在当前单词中更改到达目标所需的字母数。应该清楚为什么这是一个很好的启发式 - 它总是会被低估。您可以将邻居视为只能使用一个操作从当前单词到达的单词。应该很清楚,这种算法只需稍加修改就可以最佳地正确解决您的问题。

答案 1 :(得分:0)

我尝试制作一些有效的东西,至少在你的确切情况下。

word_before = "kitten"
word_after = "sitting"

# If the strings aren't the same length, we stuff the smallest one with spaces
if len(word_before) > len(word_after):
    word_after += " "*(len(word_before)-len(word_after))
elif len(word_before) < len(word_after):
    word_before += " "*(len(word_after)-len(word_before))

operations = []

for idx, char in enumerate(word_before):
    if char != word_after[idx]:
        if char != " ":
            operations += ["delete at "+str(idx)]
        operations += ["insert '"+word_after[idx]+"' at "+str(idx)]

print(operations)

答案 2 :(得分:0)

这应该是您正在寻找的内容,使用itertools.zip_longest将列表压缩在一起并成对迭代它们比较它们并应用正确的操作,它将操作追加到列表的末尾对于每个操作,它会比较列表是否匹配,如果不是

则会中断或继续
from itertools import zip_longest

a = "kitten"
b = "sitting"

def transform(a, b):
    ops = []
    for i, j in zip_longest(a, b, fillvalue=''):
        if i == j:
            pass
        else:
            index = a.index(i)
            print(a, b)
            ops.append('delete {} '.format(i)) if i != '' else ''
            a = a.replace(i, '')
            if a == b:
                break
            ops[-1] += 'insert {} at {},'.format(j, index if i not in b else b.index(j))
    return ops

result = transform(a, b)

print(result, ' {} operation(s) was carried out'.format(len(result)))

答案 3 :(得分:0)

由于您只有删除和插入操作,因此这是最长公共子序列问题的一个实例:https://en.wikipedia.org/wiki/Longest_common_subsequence_problem

实际上,长度kST长度Sn的字符串T中有一个共同的子序列m长度S,当且且只有您可以使用T插入和删除操作将m+n-2k转换为S。将此视为直觉:在添加和删除字母时以及在进行子序列时,字母的顺序都会被保留。

编辑:既然你要求编辑列表,那么进行编辑的一种可能方法是首先删除T中不在公共子序列中的所有字符,然后插入{{1的所有字符这不是常见的子序列。