看来这可以使用Dynamic Programming 解决。在不失一般性的情况下,我可以将问题重新表述为:
给定搜索空间S = {s1, s2, ..., sn},针对(si, sj),我们必须找到位置对(k, l),这样:
(sk, sl) == (si, sj)
-
distance(k, l) 是最小值。
该问题的递归解决方案可以通过以下方式制定:
Cost(m) =
LARGEST_NUMBER, if m = 0
Min (Cost(m-1), distance(S[m], Latest_si)), if m > 0 and S[m] == sj
Min (Cost(m-1), distance(S[m], Latest_sj)), if m > 0 and S[m] == si
Cost(m-1), if m > 0 and S[m] != (si, sj)
在哪里,
-
Cost(m) 是优化函数。它表示搜索空间S[1:m] 中(si, sj) 之间的最小距离。
-
Latest_si是si的最新位置。
-
Latest_sj是sj的最新位置。
这可以转换为空间复杂度为O(n) 的O(n) 自底向上循环来存储Cost。
这是上述算法在 Python 中的实现:
def min_phrase (S, si, sj):
Cost = []
for i in S:
Cost.append([len(S), [-1, -1]])
latest_si = -1
latest_sj = -1
for idx, v in enumerate(S):
if v == si:
if latest_sj >=0:
cost = idx - latest_sj
if cost < Cost[idx - 1][0]:
Cost[idx] = [cost, [latest_sj, idx]]
else:
Cost[idx] = Cost[idx - 1]
else:
Cost[idx] = Cost[idx - 1]
latest_si = idx
elif v == sj:
if latest_si >=0:
cost = idx - latest_si
if cost < Cost[idx - 1][0]:
Cost[idx] = [cost, [latest_si, idx]]
else:
Cost[idx] = Cost[idx - 1]
else:
Cost[idx] = Cost[idx - 1]
latest_sj = idx
else:
Cost[idx] = Cost[idx - 1]
return Cost[len(S) - 1]
if __name__ == '__main__':
S = ("one", "two", "three", "four", "five", "four", "six", "one")
si = "one"
sj = "four"
result = min_phrase(S, si, sj)
if result[1][0] == -1 or result[1][1] == -1:
print "No solution found"
else:
print "Cost: {0}".format(result[0])
print "Phrase: {0}".format(" ".join(S[result[1][0] : result[1][1] + 1]))