ย - Last update: 2023-10-31

LCS

LCS๋Š” Longest Common Subsequence์˜ ์•ฝ์ž๋กœ, ๋‘ ๋ฌธ์ž์—ด์—์„œ ์ตœ๋Œ€๋กœ ๊ณตํ†ต๋˜๋Š” ๋ถ€๋ถ„ ์ค‘ ์ œ์ผ ๊ธด ๊ฒƒ์„ ์ฐพ๋Š”๋‹ค. ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ํ‰๋ฒ”ํ•œ O(N2)O(N^2) ์ธ ๋Œ€ํ‘œ DP ์œ ํ˜•์ด์ง€๋งŒ, ๊ตฌํ˜„ ๋‚œ์ด๋„๊ฐ€ ์‚ด์ง ๊นŒ๋‹ค๋กญ๊ธฐ ๋•Œ๋ฌธ์—, ์ •๋ฆฌํ•ด๋ณธ๋‹ค.

์•„๋ž˜ ์ฝ”๋“œ๋Š” ํ”ํžˆ ์–˜๊ธฐํ•˜๋Š” LCS๋Š” ์•„๋‹ˆ๊ณ , Longest Common Substring์„ ๊ตฌํ•˜๋Š” ์ฝ”๋“œ์ธ๋ฐ, ์ตœ์ข…์ ์œผ๋กœ ๊ตฌํ•˜๋ ค๊ณ  ํ•˜๋Š” Longest Common Subsequence๋ณด๋‹ค ๊ตฌํ˜„์ด ๊ฐ„๋‹จํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์งš๊ณ  ๋„˜์–ด๊ฐ„๋‹ค.

for(int a = 1; a <= lena; ++a) {
for(int b = 1; b <= lenb; ++b) {
if (A[a] == B[b]) DP[a][b] = DP[a-1][b-1] + 1;
else DP[i][j] = 0;
}
}

์‚ฌ์‹ค ์ด ๊ฒฝ์šฐ์—๋Š” ๊ตณ์ด 2์ฐจ์› DP ๋ฐฐ์—ด์„ ์“ธ ํ•„์š”๋„ ์—†๋‹ค. 1์ฐจ์›์œผ๋กœ๋„ ์ถฉ๋ถ„ํ•˜๊ธฐ ๋•Œ๋ฌธ์—.. ๋‹ค๋งŒ, ๊ตณ์ด 2์ฐจ์›์œผ๋กœ ๋งŒ๋“  ์ด์œ ๋Š” ๊ด€์ฐฐ์„ ์œ„ํ•ด์„œ์ด๋‹ค. ์ด DP ํ…Œ์ด๋ธ”์˜ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๊ฒŒ ๋˜๋ฉด, ์ค‘๋ณต๋˜๋Š” ๋ฌธ์ž์—ด์„ ๋งŒ๋‚˜๊ฒŒ ๋˜๋ฉด ๋Œ€๊ฐ์„  ์šฐํ•˜๋‹จ ๋ฐฉํ–ฅ์œผ๋กœ ์ด๋™ํ•˜๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. ๋˜ํ•œ, ์ค‘๊ฐ„์— ์„œ๋กœ ๋‹ค๋ฅธ ๋ฌธ์ž์—ด์ด ๋‚˜์˜ค์ž๋งˆ์ž ์นผ๊ฐ™์ด DP ํ…Œ์ด๋ธ”์„ 0์œผ๋กœ ๋งŒ๋“ค์–ด ์ฃผ๋Š” ๊ฒƒ์ด ํฌ์ธํŠธ์ด๋‹ค.

์—ฌ๊ธฐ์„œ ์‚ฌ๊ณ ๋ฅผ ํ™•์žฅํ•ด๋ณด์ž. 0์œผ๋กœ ๋งŒ๋“œ๋Š” ์ด์œ ๋Š” ์—ฐ์†๋œ๋‹ค๋Š” ์กฐ๊ฑด์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ์—ฐ์†๋œ๋‹ค๋Š” ์กฐ๊ฑด์ด ์—†์„ ๋•Œ๋Š” ์–ด๋–ป๊ฒŒ ๋  ๊ฒƒ์ธ๊ฐ€? ์ด ๊ฒฝ์šฐ ํ˜„์žฌ๊นŒ์ง€์˜ ์ตœ๋Œ€ ๊ณตํ†ต ๋ถ€๋ถ„ ๊ธธ์ด๊ฐ€ ์œ ์ง€๊ฐ€ ๋˜์–ด์•ผ ํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด ์œ ์ง€๋Š” x์ถ•์œผ๋กœ ํ•ด์•ผํ•  ์ˆ˜๋„ ์žˆ๊ณ , y์ถ•์œผ๋กœ ํ•ด์•ผํ•  ์ˆ˜๋„ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— x, y์ถ•์— ๋Œ€ํ•œ max ๊ฐ’์„ ๊ตฌํ•ด์ฃผ๋ฉด ๋˜๊ฒ ๋‹ค. ๊ทธ๋ž˜์„œ ์œ„ DP ์‹์ด ์•„์ฃผ ์•ฝ๊ฐ„ ๋ฐ”๋€๋‹ค. ์ด ๋ถ€๋ถ„๋งŒ ์ˆ˜์ •์„ ํ•˜๊ฒŒ ๋˜๋ฉด, ์ฝ”๋“œ๊ฐ€ Longest Common Subsequence๋ฅผ ๊ตฌํ•˜๋Š” ์ฝ”๋“œ๋กœ ๋ณ€ํ•˜๊ฒŒ ๋œ๋‹ค.

for(int a = 1; a <= lena; ++a) {
for(int b = 1; b <= lenb; ++b) {
if (A[a] == B[b]) DP[a][b] = DP[a-1][b-1] + 1;
else DP[a][b] = max(DP[a-1][b], DP[a][b-1]);
}
}

์ž˜ ๋™์ž‘ํ• ๊นŒ? ์ด ์˜๋ฌธ์„ ํ•ด์†Œํ•˜๊ธฐ ์•ž์„œ์„œ, DP[lena][lenb]DP[lena][lenb] ๋กœ๋Š” ๊ฐ€์žฅ ๊ธด LCS์˜ ๊ธธ์ด๋งŒ์„ ์•Œ ์ˆ˜ ์žˆ์„ ๋ฟ์ธ๋ฐ, ๋งŒ์•ฝ ์ด๋Ÿฌํ•œ LCS ์ค‘ 1๊ฐœ๋ฅผ ์ถœ๋ ฅํ•˜๋ผ๋Š” ๋ฌธ์ œ๋ฅผ ๋งŒ๋‚˜๋ฉด ์–ด๋–ป๊ฒŒ ํ’€๊นŒ? ์œ„ ์ฝ”๋“œ๊ฐ€ ์ž˜ ๋™์ž‘ํ•˜๋Š”์ง€ ์•Œ์•„๋ณด๊ธฐ ์œ„ํ•ด ์ „์ฒด์ ์ธ ๊ตฌ์กฐ ์ดํ•ด์™€ ๋ฌธ์ œ ํ•ด๊ฒฐ์„ ์œ„ํ•ด ์•„๋ž˜์™€ ๊ฐ™์€ DP Table ๊ฒฐ๊ณผ๋ฅผ ์˜ˆ์‹œ๋กœ ๋ณด์ž. ๊ฐ€๋กœ์ถ•๊ณผ ์„ธ๋กœ์ถ•์€ ๊ฐ๊ฐ abc์™€ axbycz์˜ ๋ฌธ์ž์—ด์„ ํ• ๋‹นํ–ˆ๊ณ , ์ด๋“ค์˜ LCS๋Š” 33์ž„์„ ๋ฐ”๋กœ ์•Œ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค.

--abc
-0000
a0111
x0111
b0122
y0122
c0123
z0123

LCS๋ฅผ ํ•˜๋‚˜ ๊ตฌํ•˜๊ธฐ ์œ„ํ•ด ์šฐ๋ฆฌ๊ฐ€ ์ฃผ๋ชฉํ•ด์•ผํ•  ๋ถ€๋ถ„์€ ๋Œ€๊ฐ์„  ์ด๋‹ค. ์•„๋ž˜์™€ ๊ฐ™์€ ํ”„๋กœ์„ธ์Šค๋กœ ๋ฌธ์ž์—ด์„ ์ฐพ๋Š”๋‹ค.

  1. ์šฐํ•˜๋‹จ ์ขŒํ‘œ์ธ (lena,lenb)(lena, lenb) ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•œ๋‹ค.
  2. ์™ผ์ชฝ ํ˜น์€ ์œ„์ชฝ์œผ๋กœ ์ˆซ์ž๊ฐ€ ๊ฐ™์€ ์ง€์ ๊นŒ์ง€ ์ญ‰ ๋”ฐ๋ผ๊ฐ„๋‹ค.
    • ์œ„ ํ‘œ์—์„œ๋Š” (z,c)(z,c) ์œผ๋กœ ์‹œ์ž‘ํ•ด์„œ, (c,c)(c,c) ์—์„œ ์ฒ˜์Œ์œผ๋กœ ๋ฉˆ์ถ”๊ฒŒ ๋˜๊ฒ ๋‹ค.
  3. ์™ผ์ชฝ ํ˜น์€ ์œ„์ชฝ์— ๋” ์ด์ƒ ๊ฐ™์€ ์ˆซ์ž๊ฐ€ ์—†์œผ๋ฉด, ์ขŒ์ƒ๋‹จ ๋ฐฉํ–ฅ, ์ฆ‰ (xโˆ’1,yโˆ’1)(x - 1, y - 1) ์ขŒํ‘œ์— ์žˆ๋Š” ์ˆซ์ž๊ฐ€ (x,y)(x, y) ์ขŒํ‘œ์˜ ์ˆซ์ž๋ณด๋‹ค 11 ์ž‘์€ ์ˆ˜๊ฐ€ ๋œ๋‹ค. ๊ทธ ์œ„์น˜์—์„œ์˜ ๋ฌธ์ž์—ด์„ ๊ธฐ๋กํ•˜๊ณ , ๋Œ€๊ฐ์„  ๋ฐฉํ–ฅ์œผ๋กœ ์ด๋™ํ•œ๋‹ค.
  4. ์ด๋ฅผ ๋ฐ˜๋ณตํ•˜์—ฌ ์ตœ์ข…์ ์œผ๋กœ ์ˆซ์ž๊ฐ€ 0์ด ๋  ๋•Œ๊นŒ์ง€ ์ €์žฅ๋œ ๋ฌธ์ž์—ด์„ ์ฝ์œผ๋ฉด, ๊ทธ๊ฒƒ์ด LCS๊ฐ€ ๋œ๋‹ค.

2๋ฒˆ์ด ์กฐ๊ธˆ ์ดํ•ด๊ฐ€ ์•ˆ๋  ์ˆ˜ ์žˆ๋Š”๋ฐ, ๋งจ ์ฒ˜์Œ ์ฝ”๋“œ๋ฅผ ๋‹ค์‹œ ์˜ฌ๋ ค๋ณด๋ฉด, ๋ฌธ์ž์—ด์ด ๊ฐ™์„ ๋•Œ (x+1,y+1)(x+1, y+1) ๋ฐฉํ–ฅ์œผ๋กœ 1๋งŒํผ ๋”ํ•˜๋ฉด์„œ ์ „์ง„ํ–ˆ๋‹ค. ์ด๋ฅผ ์—ญ์œผ๋กœ ํ•œ ๊ฒƒ์ด๋ผ๊ณ  ๋ณด๋ฉด ๋œ๋‹ค.

์˜ˆ์‹œ ๊ตฌํ˜„ ์ฝ”๋“œ

๋‘ ๋ฌธ์ž์—ด์„ ๋ฐ›์•„ ๊ฐ€์žฅ ๊ธด LCS๋ฅผ ์ถœ๋ ฅํ•˜๋Š” ๋ฌธ์ œ์ด๋‹ค.

char A[3010];
char B[3010];
char C[3010];
int DP[3010][3010];
void solve() {
scanf("%s %s", &A[1], &B[1]);
int lena = strlen(&A[1]);
int lenb = strlen(&B[1]);
for(int b = 1; b <= lenb; ++b) {
for(int a = 1; a <= lena; ++a) {
if (A[a] == B[b]) {
DP[b][a] = DP[b - 1][a - 1] + 1;
} else {
DP[b][a] = max(DP[b - 1][a], DP[b][a - 1]);
}
}
}
// LCS ๊ธธ์ด = DP[lenb][lena]
int ca = lena, cb = lenb;
int cp = 0;
while(DP[cb][ca] != 0) {
if (DP[cb - 1][ca] == DP[cb][ca]) {
--cb;
} else if (DP[cb][ca - 1] == DP[cb][ca]) {
--ca;
} else if (DP[cb - 1][ca - 1] + 1 == DP[cb][ca]) {
C[cp++] = B[cb];
cb--; ca--;
}
}
int clen = cp;
for(int i = cp - 1; i >= 0; --i) { // ์ถœ๋ ฅ์€ ์—ญ์ˆœ์œผ๋กœ
printf("%c", C[i]);
}
printf("\n");
}
๐Ÿท๏ธ ์ฃผ์ œ ๋ชฉ๋ก: