我想计算使用插入和删除将一个字符串A转换为另一个字符串B所需的编辑,并且只需要最少的操作数。
像小猫" - > "坐在"会产生一个类似的操作列表("删除0","插入' 0","删除4", "在3","插入''在6")
是否有算法执行此操作,请注意我不想想要编辑距离,我想要实际编辑。
答案 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
实际上,长度k
和S
,T
长度S
和n
的字符串T
中有一个共同的子序列m
长度S
,当且且只有您可以使用T
插入和删除操作将m+n-2k
转换为S
。将此视为直觉:在添加和删除字母时以及在进行子序列时,字母的顺序都会被保留。
编辑:既然你要求编辑列表,那么进行编辑的一种可能方法是首先删除T
中不在公共子序列中的所有字符,然后插入{{1的所有字符这不是常见的子序列。