편집 거리 (Edit Distance)
삽입(insert), 삭제(delete), 대체(substitute) 연산을 사용하여 스트링 S를 수정하여 다른 스트링 T로 변환하고자 할 때 필요한 최소의 편집 연산 횟수
예제
S = strong
T = stone
E[i, j] = S의 처음 i개 문자를 T의 처음 j개 문자로 바꾸는데 필요한 편집 거리
E[4, 3] = 'strong' → 'stone'에 대해서, 'stro'를 'sto'로 바꾸기 위한 편집 거리
s1 → t1 ['s' → 's'] : s1 = t1 = 's' 이므로 E[1, 1] = 0
s1 → t1t2 ['s' → 'st'] : s1 = t1 = 's'이고, 't'를 삽입하므로 E[1, 2] = 1
s1s2 → t1 ['st' → 's'] : s1 = t1 = 's'이고, 't'를 삭제하므로 E[2, 1] = 1
s1s2 → t1t2 ['st' → 'st'] : s1 = t1 = 's'이고, s2 = t2 = 't' 이므로 E[2, 2] = E[1, 1] + 0 = 0
즉, E[4, 3]은 바로 그 주위의 편집 거리를 알면 해결 가능 (아래 그림 참고)
◼ E[4, 2]의 해를 알면 그 해에 t3인 'o'를 삽입 (+1)
◼ E[3, 3]의 해를 알면 그 해에 s4인 'o'를 삭제 (+1)
◼ E[3, 2]의 해를 알면 그 해에 s4와 t3의 문자가 같은 지를 비교 후 같으면 연산 X (+0) (만약 다르면 +1)
위 세 개의 값 중 가장 작은 값이 E[4, 3]
E[i, j] = min{E[i, j-1]+1, E[i-1, j]+1, E[i-1 j-1]+α}
(if si와 tj가 다르면 α=1, si와 tj가 같으면 α=0)
'strong' → 'stone'으로 바꾸는데 필요한 편집 거리
E[6, 5] = 2
def edit_distance(S, T):
m = len(S)
n = len(T)
E = [[0] * (n + 1) for _ in range(m + 1)] # 2차원 배열 생성
for i in range(n + 1): # 0번 열의 초기화
E[0][i] = i
for i in range(m + 1): # 0번 행의 초기화
E[i][0] = i
for i in range(1, m + 1):
for j in range(1, n + 1):
alpha = 0 if S[i-1] == T[j-1] else 1
E[i][j] = min(E[i][j-1]+1, E[i-1][j]+1, E[i-1][j-1]+alpha)
# print(E[i])
return E, E[m][n]
def print_array2d(arr):
for i in range(len(arr)): # 행
print(arr[i])
# 실행
if __name__ == "__main__":
s = "strong"
t = "stone"
array, editDistance = edit_distance(s,t)
print_array2d(array)
print(f"{s} -> {t} 편집 거리: {editDistance}")
'파이썬 알고리즘 > 동적 계획 알고리즘 (Dynamic Programming)' 카테고리의 다른 글
동전 거스름돈 문제 (0) | 2023.06.27 |
---|---|
배낭 문제 (0) | 2023.06.25 |
모든 쌍 최단 경로 찾기 (플로이드 워셜 알고리즘) (0) | 2023.06.24 |