In computational linguistics and computer science, edit distance is a string metric(์ธก์ ๋ฒ), i.e. a way of quantifying how dissimilar two strings (e.g., words) are to one another, that is measured by counting the minimum number of operations required to transform one string into the other.
์ถ์ฒ : https://en.wikipedia.org/wiki/Edit_distance
ํธ์ง๊ฑฐ๋ฆฌ๋ ๋ง๊ทธ๋๋ก ํ๋์ ๋ฌธ์์ด์ ๋ค๋ฅธ ๋ฌธ์์ด๋ก 'ํธ์ง'ํ๊ธฐ ์ํ ๊ฑฐ๋ฆฌ=๋น์ฉ์ ๊ณ์ฐํ๋ฏ๋ก์จ ๋ ๋ฌธ์์ด์ด ์ผ๋ง๋ ๋ค๋ฅธ์ง(=๊ฐ์์ง)๋ฅผ ํ๋จํ๋ ์๊ณ ๋ฆฌ์ฆ์ด๋ค.
์ ์์์ ์ ์ ์๋ฏ ๋ฌธ์์ด๋ผ๋ฆฌ์ ์ ์ฌ์ฑ์ ํ๋จํ๊ธฐ ๋๋ฌธ์, ์์ฐ์ด ์ฒ๋ฆฌ์์ ์คํ ๋ง ์ฒดํฌ๋ฅผ ํ๊ฑฐ๋, ์๋ฌผ์ ๋ณดํ์์ ์ผ๊ธฐ์์ด์ ์ ์ฌ์ฑ์ ํ๋จ๋๋ฐ ์ฐ์ด๊ธฐ๋ ํ๋ค.
์คํ ๋ง ์ฒดํฌ์ ์ข์ ์.
ํธ์ง์ ์ข ๋ฅ์๋ ํฌ๊ฒ 3๊ฐ์ง๊ฐ ์๋ค. ์ฝ์ (Insertion), ์ญ์ (Deletion), ๋์ฒด(Substitution).
- Insertion of a single symbol.
If , then inserting the symbol produces .
This can also be denoted , using to denote the empty string.- Deletion of a single symbol changes to .
- Substitution of a single symbol for a symbol changes to .
์ด๋ค ์ค์ ์ด๋ค ํธ์ง์ฐ์ฐ์ ํ์ฉํ๋ ์ง์ ๋ฐ๋ผ Edit Distance ์๊ณ ๋ฆฌ์ฆ์ ์ข ๋ฅ๊ฐ ํ์๋๋ค.
์ด ๊ธ์์๋ ์ฝ์
, ์ญ์ , ๋์ฒด๋ฅผ ํ์ฉํ๋ Levenshtein distance์ ์๊ณ ๋ฆฌ์ฆ๊ณผ,
์ฝ์
, ์ญ์ ๋ง์ ํ์ฉํ๋ longest common subsequence (LCS) distance ์๊ณ ๋ฆฌ์ฆ์ ์์๋ณธ๋ค.
๋จผ์ ๊ฐ๋จํ ํธ์ง ์์๋ฅผ ํตํด ๋์ ๋น๊ตํด๋ณด์.
์ผ๋จ ์ฌ๊ธฐ์๋, ๊ฐ๊ฐ์ ์๊ณ ๋ฆฌ์ฆ์ ํตํด ์ต์ํ์ ํธ์งํ์๋ฅผ ๊ตฌํ๊ณ ์ ํ๋ค.
The Levenshtein distance
"kitten" โก๏ธ "sitting" distance is 3.
LCS distance
"kitten" โก๏ธ "sitting" distance is 5.
์ด์ฒ๋ผ ๋ ์๊ณ ๋ฆฌ์ฆ์ ๊ฒฐ๊ณผ๊ฐ ๋ค๋ฅธ๋ฐ, ์ฐ์์๊ฐ ์๋ก ์กฐ๊ธ์ฉ ๋ค๋ฅด๋ค.
๋ฆฌ๋ฒค์ํ์ธ์ ํธ์ง๊ฑฐ๋ฆฌ๋ฅผ ๋จผ์ ์์๋ณด์.
S = 'strong' โก๏ธ T = 'stone'์ ๊ฒฝ์ฐ๋ฅผ ์๋ก ๋ค์ด๋ณด์.
๋ง์ผ ๊ฐ ์ ๋๋ถ(prefix)์ ๋ํด ํธ์ง๊ฑฐ๋ฆฌ๋ฅผ ๋ฏธ๋ฆฌ ์๊ณ ์๋ค๋ฉด,
์๋ฅผ ๋ค์ด 'stro' โก๏ธ 'sto'์ ํธ์ง๊ฑฐ๋ฆฌ๋ฅผ ๋ฏธ๋ฆฌ ์๊ณ ์๋ค๋ฉด ๋จ์ ๋ฌธ์์ด('ng'์ 'ne')์ ๋ํ ํธ์ง๊ฑฐ๋ฆฌ๋ฅผ ์ฐพ์์ผ๋ก์จ, ์ฃผ์ด์ง ์
๋ ฅ๊ฐ ์ ์ฒด์ ๋ํ ํธ์ง๊ฑฐ๋ฆฌ๋ฅผ ๊ตฌํ ์ ์์ ๊ฒ์ด๋ค.
์์๋๋ก DP ๋ฅผ ํตํด ๋ถ๋ถ๋ฌธ์ ๋ฅผ ํด๊ฒฐํด ๋๊ฐ๋ฉด์ ๊ณ์ฐ๋๋ค. ๋ถ๋ถ๋ฌธ์ ์ ์ ์๋ ๋ค์๊ณผ ๊ฐ๋ค.
๋ ์ ์์์๋ถํฐ ๊ฐ์ ๋ฌธ์๋ฅผ, ์ ์์์๋ถํฐ ๊ฐ์ ๋ฌธ์๋ก ๋ณํ์ํค๋ ๋ฐ ํ์ํ ์ต์ ํธ์ง๊ฑฐ๋ฆฌ์ด๋ค.
('stro' โก๏ธ 'sto') ๋ฅผ ๊ตฌํ๋ ค๊ณ ํ๋ค๋ฉด ๋ค์์ 3๊ฐ์ง ๊ฒฝ์ฐ๋ฅผ ์ดํด๋ณผ ์ ์๋ค.
- ('stro' โก๏ธ 'st')์ ๊ฐ์ ์๊ณ ์๋ค๋ฉด, ๋ค์ ๋งํด 'stro'๋ฅผ 'st'๋ก ๋ฐ๊พธ๋ ์ต์์ ํธ์ง๊ฑฐ๋ฆฌ๋ฅผ ์ด๋ฏธ ์๊ณ ์๋ค๋ฉด, ๊ทธ ํธ์ง๊ฑฐ๋ฆฌ์ ์ฝ์ ์ฐ์ฐ์ ๋น์ฉ ํ๋๋ง ์ถ๊ฐํด์ฃผ๋ฉด ๋๋ค.
'stro' โก๏ธ 'st' ํ ํ, T์ชฝ์ 'o'ํ๋๋ง ์ฝ์ ํด ์ฃผ๋ฉด ๋๊ธฐ ๋๋ฌธ์ด๋ค.- ('str' โก๏ธ 'sto')์ ๊ฐ์ ์๊ณ ์๋ค๋ฉด, ๋ค์ ๋งํด 'str'๋ฅผ 'sto'๋ก ๋ฐ๊พธ๋ ์ต์์ ํธ์ง๊ฑฐ๋ฆฌ๋ฅผ ์ด๋ฏธ ์๊ณ ์๋ค๋ฉด, ๊ทธ ํธ์ง๊ฑฐ๋ฆฌ์ ์ญ์ ์ฐ์ฐ์ ๋น์ฉ ํ๋๋ง ์ถ๊ฐํด์ฃผ๋ฉด ๋๋ค.
S์ชฝ 'stro'์ 'o'ํ๋๋ง ๋นผ์ค ์ํ์์ 'str' โก๏ธ 'sto' ํ๋ฉด ๋๊ธฐ ๋๋ฌธ์ด๋ค.- ('str' โก๏ธ 'st')์ ๊ฐ์ ์๊ณ ์๋ค๋ฉด, ๊ธฐ์กด S์ ๋๋ฌธ์๋ฅผ ๊ธฐ์กด T์ ๋๋ฌธ์๋ก ๋์ฒดํ๋ ํธ์ง ๋น์ฉ์ ์ถ๊ฐํด์ฃผ๋ฉด๋๋ค. 'str' โก๏ธ 'st' ํ๊ณ ํด๋น ๋์ฒด๋ฅผ ์งํํ๋ฉด ๋๊ธฐ ๋๋ฌธ์ด๋ค. ์ฌ๊ธฐ์๋ 'o'๋ฅผ 'o'๋ก ๋์ฒดํ๋ ๋น์ฉ, ์ฆ 0์ ์ถ๊ฐํ๊ฒ ๋๋ค. ๊ฐ๋งํ ๋ฌ๋ ๋๊ธฐ ๋๋ฌธ.
์ด๋ฅผ ๋์ํ ํด๋ณด๋ฉด ์๋์ ๊ฐ๋ค.
์ด์ ์ด๋ฌํ ํน์ฑ์ ์ด์ฉํด dpํ
์ด๋ธ์ ์ฑ์ ๋๊ฐ๋ฉด์ ์ ์ฒด ์
๋ ฅ์ ๋ํ ํด๋ฅผ ๊ตฌํด๋ณด์.
์๋๋ ์ ํ์๊ณผ ์ ์ฒด์ ์ธ ์ฝ๋์ ์งํ์ด๋ค.
์ฒ์ ํ
์ด๋ธ์ ์ด๊ธฐํ๋ ๋ค์๊ณผ ๊ฐ์ด ํ๋ฉด ๋๋ค.
S = ๊ธฐ์กด ๋ฌธ์์ด, T = ๋ชฉํ ๋ฌธ์์ด, m = S์ ๊ธธ์ด, n = T์ ๊ธธ์ด
- ๐ธ[๐,0] = ๐, ๐ธ[0,๐] = ๐ for ๐ = 0,1,โฆ,๐ and ๐ = 0,1,โฆ,๐
- For ๐ = 1,2,โฆ,๐ and ๐ = 1,2,โฆ,๐
๐ธ[๐, ๐] = min{ ๐ธ[๐ - 1, ๐] + 1, ๐ธ[๐, ๐ - 1] + 1, ๐ธ[๐ โ 1, ๐ โ 1] + ๐ผ}
where ๐ผ = 1 if 0 otherwise
(์๋๋ ๋์ฒด์ฐ์ฐ์ด ๊ฐ๋ฅํ๋ค๋ฉด ๋ค๋ฅธ ๋ฐฉํฅ๋ค๊ณผ์ ๋น๊ต ์์ด ๋ฌด์กฐ๊ฑด ๋์ฒด์ฐ์ฐ์ผ๋ก ์งํํ๋ ์ ํ์. ์ด ๋ฐฉ์์ ์ฌ์ฉํ๋ฉด LCS์์ ํธํ์ด ๊ฐ๋ฅํ๋ค. ์ฆ ๋ฆฌ๋ฒค์ํ์ธ์ผ๋ก ๊ณ์ฐ์ ํ๊ณ back-tracing์ผ๋ก LCS์ ๊ธธ์ด๋ฅผ ์ค๋ต์์ด ๊ตฌํ ์ ์๋ค.)
for i 0 to m E[i, 0] = i // 0 ๋ฒ ์ด์ ์ด๊ธฐํ
for j= 0 to n E[0 ,j] = j // 0 ๋ฒ ํ์ ์ด๊ธฐํ
for i 1 to m
for j= 1 to n
E[i, j] = min{E[i,j-1] + 1 , E[i-1 ,j] + 1 , E[i-1,j-1] + a}
return E[m, n]
m*n ํฌ๊ธฐ์ ํ
์ด๋ธ์ ํ๋์ฉ ์ฑ์๋๊ฐ์ผ ํ๋ฏ๋ก ์๊ฐ ๋ณต์ก๋๋ ์ด ๋๋ค.
์์ T์ ๊ฐ ๋ถ๋ถ ๋ฌธ์์ด('s','st, ... ,'stone')๋ก ํธ์งํ๋ ๋น์ฉ์ ๊ทธ๋ฅ ๊ทธ ๋ฌธ์์ด์ ๊ธธ์ด๋งํผ ์ฝ์
ํด์ฃผ๋ ๋น์ฉ์ด๋ค. ๋ฐ๋ผ์ j = 1,2,...,T์ ๊ธธ์ด ์ผ๋ E[0,j] = j ์ด๋ค.
๋ง์ฐฌ๊ฐ์ง๋ก S์ ๊ฐ ๋ถ๋ถ ๋ฌธ์์ด์์ ๋ก ํธ์งํ๋ ๋น์ฉ์ ๊ทธ ๋ฌธ์์ด์ ๊ธธ์ด๋งํผ ์ญ์ ํด์ฃผ๋ ๋น์ฉ์ด๋ค. ๋ฐ๋ผ์ i = 1,2,...,S์ ๊ธธ์ด ์ผ๋ E[i,0] = i ์ด๋ค.
์ดํ์ ์ ํ์์ ๋ฐ๋ผ ํ
์ด๋ธ์ ์ฑ์๋๊ฐ๋ค๋ณด๋ฉด, dp[m][n]์ด ์ ์ฒด ์
๋ ฅ๊ฐ์ ๋ํ ์ต์ ํธ์ง ๊ฑฐ๋ฆฌ๊ฐ ๋๋ค.
์ต์ ํธ์ง๊ฑฐ๋ฆฌ ๊ฐ ๋ฟ๋ง ์๋๋ผ, ๊ฐ ๊ณผ์ ์์์ ์ฐ์ฐ์ ์ข
๋ฅ๋ ํ์ธํ ์ ์๋ค. ๋ค๋ง ์ต์ข
๊ฒฐ๊ณผ๋ฅผ ๊ตฌํ ํ ๊ณ์ฐ ๊ณผ์ ์ ๊ฑฐ์ฌ๋ฌ ์ฌ๋ผ๊ฐ๋ฉด์(back-tracing) ๊ฐ ์ฐ์ฐ์ ์ข
๋ฅ๋ฅผ ํ์
ํด์ผ ํ๋ค.
์ต์ข ์ธ๋ฑ์ค (m,n)๋ถํฐ ์์ํด ์ด์ ์ ์ธ ๋ฐฉํฅ ์ค์์ ์ต์๊ฐ์ด ์ด๋ ๋ฐฉํฅ์ผ๋ก๋ถํฐ ์๋์ง๋ฅผ ์ฒดํฌํ๋ฉด์ ์ฐ์ฐ์ ์ข ๋ฅ๋ฅผ ์์๋ธ๋ค.
์๋๋ ์ด์ ๊ฐ์ ๋ฐฉ๋ฒ์ผ๋ก ์ฌ๋ฌ ํ
์คํธ์ผ์ด์ค์ ์ต์ ํธ์ง ๋น์ฉ๊ณผ ์ฐ์ฐ ๊ณผ์ ์ ๋ํ๋ธ ๊ฒฐ๊ณผ์ด๋ค.
๋ฆฌ๋ฒค์ํ์ธ์ ํธ์ง๊ฑฐ๋ฆฌ ๊ณ์ฐ๊ณผ์ ์ฐจ์ด์ ์ ๋์ฒด์ฐ์ฐ์ ํ์ฉํ์ง ์๋๋ค๋ ์ ์ด๋ค.
ํ์ง๋ง ๋์ฒด์ฐ์ฐ์ ํ์ฉํ์ง ์๋ ๊ฒ์ด ์ฐ์ฐ์ ์ข
๋ฅ๋ฅผ ํ์ ์ํค๊ธฐ ์ํจ์ด๋ผ๊ธฐ ๋ณด๋ค,
LCS distacne๋ฅผ ํตํด ์ป๊ณ ์ ํ๋ ๊ฒฐ๊ณผ๋ฅผ ์ํด ๋์ฒด์ฐ์ฐ์ ํน๋ณ์ทจ๊ธ ํ๋ ๊ฒ์ด๋ค.
LCS distacne๋ฅผ ํตํด ์ป๊ณ ์ ํ๋ ๊ฒ์ '์ต์ฅ ๊ณตํต ๋ถ๋ถ ์์ด์ ๊ธธ์ด'์ ๊ทธ '์์ด'์ด๋ค.
๋ฐ๋ผ์ ๋ฆฌ๋ฒค์ํ์ธ ํธ์ง๊ฑฐ๋ฆฌ์ ๊ณผ์ ๊ณผ ๋งค์ฐ ์ ์ฌํ๊ฒ ๋์ํ๋ฉด์๋,
'๋น์ฉ์ด ๋ค์ง ์๋ ๋์ฒด์ฐ์ฐ'์ ๊ฐ์์, ํด๋น ์ฐ์ฐ์ ๋์์ด ๋์๋ ๋ฌธ์๋ฅผ ์์๋ด๊ณ ์ ํ๋ ๊ฒ์ด ์ด ์๊ณ ๋ฆฌ์ฆ์ ๋ชฉํ๋ผ๊ณ ํ ์ ์๋ค.
์ ํ์์ ๋จผ์ ์ดํด๋ณด์.
์์์ ์ธ๊ธํ๋ฏ, ํธ์ง๊ฑฐ๋ฆฌ ์์ฒด๋ฅผ ๊ณ์ฐํ๋ ๊ฒ์ด ์ฃผ ๋ชฉ์ ์ด ์๋๋ฏ๋ก, ํ์ฉ๋ ์ฐ์ฐ(์ฝ์
, ์ญ์ )์ ๋ํ ๋น์ฉ ๊ณ์ฐ์ด ์๋ค. ๋ค๋ง ์ ๊ฒฝ์ฐ, ์ฆ '๋น์ฉ์ด ๋ค์ง ์๋ ๋์ฒด์ฐ์ฐ'์ด ๊ฐ๋ฅํ ๊ฒฝ์ฐ์ 1์ ๋ํด์ค์ผ๋ก์จ ๊ณตํต ๋ถ๋ถ ์์ด์ ๊ธธ์ด๋ฅผ 1๋๋ฆฌ๊ณ , ์ ๊ฒฝ์ฐ ํด๋น ์ฐ์ฐ์ด ๋ถ๊ฐ๋ฅ ํ๋ฏ๋ก, ์ฝ์
์ญ์ ์ค์์ ํ๋๋ฅผ ๊ณ ๋ฅด๋๋ฐ, ์ด ์ค max๊ฐ์ ์ ํํด ๊ณตํต ๋ถ๋ถ ์์ด์ ๊ธธ์ด๊ฐ ์ต์ฅ์ผ๋ก ์ ์ง๋ ์ ์๋๋ก ํ๋ ๊ฒ์ด๋ค.
์๋๋ ์ด์ ๋ํ ์์ฌ์ฝ๋.
function LCSLength(X[1..m], Y[1..n])
C = array(0..m, 0..n)
for i := 0..m
C[i,0] = 0
for j := 0..n
C[0,j] = 0
for i := 1..m
for j := 1..n
if X[i] = Y[j]
C[i,j] := C[i-1,j-1] + 1
else
C[i,j] := max(C[i,j-1], C[i-1,j])
return C[m,n]
์ด๋ฌํ ์๋ฆฌ๋ก R = 'GAC', C = 'AGCAT' ์ ๋ํ LCS๋ฅผ ๊ตฌํ๋ค๊ณ ํ์ ๋,
์์ฑ๋ dpํ
์ด๋ธ์ ๋ค์๊ณผ ๊ฐ๋ค.
ํ ์ด๋ธ ๋ง์ง๋ง ์ ์ ์๋ 2๊ฐ LCS์ ๊ธธ์ด๊ฐ ๋๋ค.
๊ทธ ์์ด์ ์ง์ ๊ตฌํ๊ณ ์ ํ ๋๋, ์ญ์ back-tracing์ ์ด์ฉํ๋ค.
'๋น์ฉ์ด ๋ค์ง ์๋ ๋์ฒด ์ฐ์ฐ'์ด ํ์ฌ ์ธ๋ฑ์ค์์ ๊ฐ๋ฅํ์ง ํ์ธํ๋ค. ์์์๋ ์ฃผํฉ์์ผ๋ก ํ์๋ ์ธ๋ฑ์ค๊ฐ ํด๋น๋๋ค.
๊ฐ๋ฅํ๋ค๋ฉด LCS์ ์ถ๊ฐํ๊ณ , ๋ถ๊ฐํ๋ค๋ฉด ์ฝ์
(ํ์นธ ์ผ์ชฝ), ์ญ์ (ํ์นธ ์)์ค ์ต๋๊ฐ์ ์ฐพ์ ๋ค์ ์งํํ๋ค.
๋จ, LCS๊ฐ ์ฌ๋ฌ๊ฐ ์ผ ์๋ ์๊ธฐ ๋๋ฌธ์ ํ๋์ LCS๋ฅผ ์ฝ์ด๋ผ ๋์, ๋ชจ๋ LCS๋ฅผ ์ ๋ถ ์ฐพ์ ๋์ ์ฝ๋๊ฐ ๋ค๋ฅด๋ค.
function backtrack(C[0..m,0..n], X[1..m], Y[1..n], i, j)
if i = 0 or j = 0
return ""
if X[i] = Y[j]
return backtrack(C, X, Y, i-1, j-1) + X[i]
if C[i,j-1] > C[i-1,j]
return backtrack(C, X, Y, i, j-1)
return backtrack(C, X, Y, i-1, j)
function backtrackAll(C[0..m,0..n], X[1..m], Y[1..n], i, j)
if i = 0 or j = 0
return {""}
if X[i] = Y[j]
return {Z + X[i] for all Z in backtrackAll(C, X, Y, i-1, j-1)}
R := {}
# C[i-1,j] == C[i,j-1]์ธ ๊ฒฝ์ฐ ์๋์ a,b ๋๋ค ๋ง์กฑํด ๋๋ค ์คํ๋๋ค.
# ํ์ชฝ์ด ํด๊ฒฝ์ฐ a์ b ์ค ํ๋๋ง ์คํ๋๋ค.
if C[i,j-1] โฅ C[i-1,j] # a
R := backtrackAll(C, X, Y, i, j-1)
if C[i,j-1] โค C[i-1,j] # b
R := R โช backtrackAll(C, X, Y, i-1, j) # a๊ฐ ์คํ๋์์ ๋๋ฅผ ๋๋นํ์ฌ R๊ณผ ํฉ์ณ์ค๋ค.
return R
https://en.wikipedia.org/wiki/Edit_distance
https://en.wikipedia.org/wiki/Longest_common_subsequence_problem