これは動的計画法を使用して解決できるようです。一般性を失うことなく、質問を次のように言い換えることができます。
検索空間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)
最適化関数です。(si, sj)
検索空間内の最小距離を表しますS[1:m]
。
Latest_si
は の最新の位置ですsi
。
Latest_sj
は の最新の位置ですsj
。
これは、 to storeO(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]))