1. ๊ฐ๋ โฝ
๋ผ๋น-์นดํ(Rabin-Karp) ์๊ณ ๋ฆฌ์ฆ์ด๋ ํด์ฑ(Hashing)์ ์ด์ฉํ ๋ฌธ์์ด ๋งค์นญ ์๊ณ ๋ฆฌ์ฆ์ด๋ค. ๋น๊ตํ๊ณ ์ ํ๋ ๋ฌธ์๋ค๊ณผ ํจํด์ ๋ฌธ์๋ค์ ์ผ์ผ์ด ๋น๊ตํ๋ ๋์ ์ ๋ฌธ์์ด์ ํด์๊ฐ์ ๋น๊ตํ๋ ๋ฐฉ์์ผ๋ก ์งํ๋๋ค.
2. ๋์๋ฐฉ์(์ฐ์ต์ฉ) ๐
๋์ ๋ฐฉ์์ ์๋์ ๊ฐ๋ค.
- ํด์ ํจ์๋ฅผ ์ค์ ํ๋ค.
- ํด์ ํจ์๋ฅผ ์ด์ฉํ์ฌ ํจํด์ ํด์๊ฐ์ ๊ตฌํ๋ค.
- ๋น๊ตํ๊ณ ์ ํ๋ ๋ฌธ์์ด์ ํด์๊ฐ์ ๊ตฌํ๋ค.
- ์ผ์นํ๋ฉด ํจํด๊ณผ ์ฐพ์ ๋ฌธ์์ด์ 1:1 ๋น๊ตํ๋ค.
์ผ์นํ์ง ์์ผ๋ฉด ๋น๊ตํ๊ณ ์ ํ๋ ๋ฌธ์์ด์ ํ ์นธ ๋ค๋ก ์ฎ๊ฒจ์ 3๋ฒ๋ถํฐ ๋ค์ ์์ํ๋ค.
ํด์๊ฐ์ด ๊ฐ๋๋ผ๋ 1:1 ๋งค์นญ์ ํตํด์ ์ต์ข ์ ์ผ๋ก ํจํด๊ณผ ๋น๊ตํ๊ณ ์ ํ๋ ๋ฌธ์์ด์ด ์ผ์นํ๋์ง ํ์ธํ๋ ์ ์ฐจ๊ฐ ํ์ํ๋ค. ๊ทธ ์ด์ ๋ ํด์๊ฐ์ด ๊ฐ๋ค๊ณ ํด์ ๋ฌด์กฐ๊ฑด ๊ฐ์ ๋ฌธ์์ด์ด๋ผ๊ณ ๋ณด์ฅํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
๋งค์ฐ ๊ฐ๋จํ ์์๋ฅผ ํตํด ๋์๋ฐฉ์์ ์ดํดํด ๋ณด์. '4 1 2 3 5'๋ผ๋ ๋ฌธ์์ด๊ณผ '1 2 3'์ด๋ผ๋ ํจํด์ด ์ฃผ์ด์ก๋ค๊ณ ํ์.
ํด์ํจ์์ ๋ฌธ์์ด์ 10์ง์๋ก ํํํ๋ ๊ฒ์ด๋ผ๊ณ ํ์. ์๋ฅผ ๋ค์ด, ํจํด '1 2 3'์ ํด์๊ฐ์ 123์ด ๋๊ณ '4 3 1'์ ํด์๊ฐ์ 431์ด ๋ ๊ฒ์ด๋ค.
์์์ ์ดํด๋ณธ ๋์๋ฐฉ์ ์ด์ฉํ์ฌ ํจํด๊ณผ ์ผ์นํ๋ ๋ฌธ์์ด์ ์ฐพ์๋ณด์.
1. ๋น๊ตํ๊ณ ์ ํ๋ ๋ฌธ์์ด์ ํด์๊ฐ(412) != ํจํด์ ํด์๊ฐ(123)
2. ๋น๊ตํ๊ณ ์ ํ๋ ๋ฌธ์์ด์ ํด์๊ฐ(123) == ํจํด์ ํด์๊ฐ(123)
3. 1:1 ๋งค์นญ ๋น๊ต
ํด์๊ฐ๋ ์ผ์นํ๊ณ 1:1 ๋งค์นญ๋ ์ฑ๋ฆฝํ๋ฏ๋ก ํจํด๊ณผ ์ผ์นํ๋ ๋ฌธ์์ด์ ์ฐพ๊ฒ ๋์๋ค.
3. ๋์๋ฐฉ์(์ค์ ์ฉ) ๐
์์ ๋ฐฉ์์ผ๋ก ํด์ ํจ์๋ฅผ ์ฌ์ฉํ๋ฉด ํด์๊ฐ์ด ๋๋ฌด ์ปค์ง๋ ๋ฌธ์ ๊ฐ ์กด์ฌํ๋ค. ๋ผ๋น-์นดํ ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉ๋๋ ์ผ๋ฐ์ ์ธ ํด์ ํจ์๋ ๋ค์๊ณผ ๊ฐ๋ค.
ํด์ ํจ์๋ '๊ฐ ๋ฌธ์์ ์์คํค์ฝ๋ ๊ฐ์ 2์ ์ ๊ณฑ ์๋ฅผ ์ฐจ๋ก๋๋ก ๊ณฑํ์ฌ ๋ํด์ฃผ๋ ๊ฒ'์ ์ฌ์ฉํ๋ค. ์ด ๋ฐฉ์์ ์ฌ์ฉํ๋ฉด ์๋ก ๋ค๋ฅธ ๋ฌธ์์ด์ ๊ฒฝ์ฐ ์ผ๋ฐ์ ์ผ๋ก ๋ค๋ฅธ ํด์ ๊ฐ์ ๊ฐ์ง๊ฒ ๋๋ค.
์๋ฅผ ๋ค์ด 'aba'์ ํด์ ๊ฐ์ '(97 * 2^2) + (98 * 2^1) + (97 * 2^0) = 388 + 196 + 97 = 681', 'bab'์ ํด์๊ฐ์ '(98 * 2^2) + (97 * 2^1) + (98 * 2^0) = 392 + 194 + 98 = 684'๊ฐ ๋๊ฒ ๋๋ค.
๋ฌธ์์ด 'ababacab'์ ํจํด 'baca'๋ฅผ ์ด์ฉํ์ฌ ์ค์ ์ ์ฉ์ ํด๋ณด์. ํจํด์ ํด์๊ฐ์ '(98 * 2^3) + (97 * 2^2) + (99 * 2^1) + (97 * 2^0) = 1467'์ด๋ค.
1. ๋น๊ตํ๊ณ ์ ํ๋ ๋ฌธ์์ด์ ํด์๊ฐ : (97 * 2^3) + (98 * 2^2) + (97 * 2^1) + (98 * 2^0) = 1460
ํจํด์ ํด์๊ฐ(1467)๊ณผ ๋ถ์ผ์น
2. ๋น๊ตํ๊ณ ์ ํ๋ ๋ฌธ์์ด์ ํด์๊ฐ : (98 * 2^3) + (97 * 2^2) + (98 * 2^1) + (97 * 2^0) = 1465
ํจํด์ ํด์๊ฐ(1467)๊ณผ ๋ถ์ผ์น
3. ๋น๊ตํ๊ณ ์ ํ๋ ๋ฌธ์์ด์ ํด์๊ฐ : (97 * 2^3) + (98 * 2^2) + (97 * 2^1) + (99 * 2^0) = 1461
ํจํด์ ํด์๊ฐ(1467)๊ณผ ๋ถ์ผ์น
4) ๋น๊ตํ๊ณ ์ ํ๋ ๋ฌธ์์ด์ ํด์๊ฐ : (98 * 2^3) + (97 * 2^2) + (99 * 2^1) + (97 * 2^0) = 1467
ํจํด์ ํด์๊ฐ(1467)๊ณผ ์ผ์น
5. 1:1 ๋งค์นญ ๋น๊ต
ํด์๊ฐ๋ ์ผ์นํ๊ณ 1:1 ๋งค์นญ๋ ์ฑ๋ฆฝํ๋ฏ๋ก ํจํด๊ณผ ์ผ์นํ๋ ๋ฌธ์์ด์ ์ฐพ๊ฒ ๋์๋ค.
4. Rolling Hash โพ
Rolling Hash๋ฅผ ์ด์ฉํ๋ค๋ฉด ๋น๊ตํ๊ณ ์ ํ๋ ๋ฌธ์์ด์ ํด์๊ฐ์ ๋ ๊ฐ๋จํ๊ฒ ๊ตฌํ ์ ์๋ค. Rolling Hash๋ Sliding Window์ ๊ฐ์ด ๋ฌธ์์ด์ ํ์ผ๋ฉด์ ํด์๊ฐ์ ๊ตฌํ๋ ๋ฐ ์ฌ์ฉ๋๋ค. ๋ฐฉ๋ฒ์ ์ค๋ณต๋๋ ํด์๊ฐ์ ๊ทธ๋๋ก ๋๊ณ ์ ๋ฐ์ดํธ๋๋ ๋ถ๋ถ๋ง ํด์๊ฐ์ ๊ณ์ฐํด ์ฃผ๋ ๊ฒ์ด๋ค. (Sliding Window์ ๊ฐ์ ๋ฐฉ๋ฒ์ด๋ค.)
์์์ ์ฌ์ฉํ ํด์ ํจ์๋ฅผ ์ด์ฉํ๋ค๋ฉด, ์๋ก์ด ๋ฌธ์์ด์ ํด์๊ฐ์ '2 * (์ด์ ๋ฌธ์์ด์ ํด์๊ฐ - ๊ฐ์ฅ ์์ ์๋ ๋ฌธ์์ ๊ฐ) + ์๋ก ๋ค์ด์จ ๋ฌธ์์ ๊ฐ'์ด๋ผ๊ณ ํ ์ ์๋ค. '์ด์ ์ ํด์๊ฐ์ ๊ตฌํ ๋ฐฉ์'๊ณผ 'Rolling Hash๋ฅผ ์ด์ฉํด์ ๊ฐ์ ๊ตฌํ๋ ๋ฐฉ์'์ ๋น๊ตํ๋ฉด์ ์ดํด๋ณด์.
[๊ธฐ์กด ๋ฐฉ์]
์ฃผ์ด์ง ๋ฌธ์์ด : ababacab
- ๋น๊ตํ ๋ฌธ์์ด : abab
ํด์๊ฐ : (97 * 2^3) + (98 * 2^2) + (97 * 2^1) + (98 * 2^0) = 1460 - ๋น๊ตํ ๋ฌธ์์ด : baba
ํด์๊ฐ : (98 * 2^3) + (97 * 2^2) + (98 * 2^1) + (97 * 2^0) = 1465 - ๋น๊ตํ ๋ฌธ์์ด : abac
(97 * 2^3) + (98 * 2^2) + (97 * 2^1) + (99 * 2^0) = 1461 - ๋น๊ตํ ๋ฌธ์์ด : baca
(98 * 2^3) + (97 * 2^2) + (99 * 2^1) + (97 * 2^0) = 1467
[Rolling Hash๋ฅผ ์ด์ฉํ๋ ๋ฐฉ์]
์ฃผ์ด์ง ๋ฌธ์์ด : ababacab
- ๋น๊ตํ ๋ฌธ์์ด : abab
ํด์๊ฐ : (97 * 2^3) + (98 * 2^2) + (97 * 2^1) + (98 * 2^0) = 1460 - ๋น๊ตํ ๋ฌธ์์ด : baba
ํด์๊ฐ : 2 * (1460 - (97 * 2^3)) + 97 = 1465 - ๋น๊ตํ ๋ฌธ์์ด : abac
ํด์๊ฐ : 2 * (1460 - (98 * 2^3)) + 99 = 1461 - ๋น๊ตํ ๋ฌธ์์ด : baca
ํด์๊ฐ : 2 * (1460 - (97 * 2^3)) + 97 = 1467
5. MOD & ์ค๋ฒํ๋ก์ฐ ๐
์ ํํ ํด์๊ฐ์ ์ผ์น ์ฌ๋ถ๋ฅผ ๊ฒ์ฆํ๊ธฐ ์ํด์ ๋ชจ๋๋ฌ ์ฐ์ฐ์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ๊ฐ ์๋ค. ํ์ง๋ง, ์ผ๋ฐ์ ์ผ๋ก ์ค๋ฒํ๋ก์ฐ๊ฐ ๋ฐ์ํ๋๋ผ๋ ํด์๊ฐ์ ๋์ผํ๋ค๊ณ ๋ณผ ์ ์๊ธฐ ๋๋ฌธ์ ๋ชจ๋๋ฌ ์ฐ์ฐ์ ์ฌ์ฉํ์ง ์์๋ ์ ์์ ์ผ๋ก ๋์ํ๋ค. (๋ ์์ ์ ์ธ ํ๋ก๊ทธ๋จ์ ์์ฑํ๊ณ ์ ํ๋ค๋ฉด ๋ชจ๋๋ฌ ์ฐ์ฐ์ ์ฌ์ฉํ๋๋ก ํ์.)
6. ๊ตฌํ(JAVA) ๐ฑ
public static void main(String[] args) {
String str = "ababacab";
String pattern = "baca";
int findIdx = 0;
boolean isFind = false;
int strLen = str.length();
int patternLen = pattern.length();
int power = 1;
int compareStrHash = 0;
int patternHash = 0;
for(int i = 0; i <= strLen - patternLen; i++) {
// ์ฒซ ๋น๊ต ๋ฌธ์์ด๊ณผ ํจํด ํด์๊ฐ ๊ตฌํ๊ธฐ
if(i == 0) {
for(int j = 0; j < patternLen; j++) {
compareStrHash += str.charAt(patternLen - 1 - j) * power;
patternHash += pattern.charAt(patternLen - 1 - j) * power;
if(j < patternLen - 1) {
power *= 2;
}
}
}
else {
compareStrHash = 2 * (compareStrHash - str.charAt(i - 1) * power)
+ str.charAt(patternLen - 1 + i);
}
// ํด์๊ฐ์ด ์ผ์นํ๋ ๊ฒฝ์ฐ // 1:1 ๋งค์นญ ๋น๊ต
if(compareStrHash == patternHash) {
for(int j = 0; j < patternLen; j++) {
if(str.charAt(i + j) != pattern.charAt(j)) {
break;
}
if(j == patternLen - 1) {
isFind = true;
findIdx = i;
}
}
}
if(isFind) {
break;
}
}
if(isFind) {
System.out.println(findIdx + "๋ฒ์งธ์์ ์ผ์นํ๋ ๋ฌธ์์ด์ ์ฐพ์์ต๋๋ค.");
}
else {
System.out.println("์ผ์นํ๋ ๋ฌธ์์ด์ ์ฐพ์ง ๋ชปํ์ต๋๋ค.");
}
// 3๋ฒ์งธ์์ ์ผ์นํ๋ ๋ฌธ์์ด์ ์ฐพ์์ต๋๋ค.
}
7. ์๊ฐ๋ณต์ก๋ ๐ณ
์ฃผ์ด์ง ๋ฌธ์์ด์ ๊ธธ์ด๊ฐ N์ด๊ณ ํจํด์ ๊ธธ์ด๊ฐ M์ด๋ผ๊ณ ํ ๋, ์ต์ ์ ๊ฒฝ์ฐ ์๊ฐ๋ณต์ก๋๋ O(NM)์ ๊ฐ์ง๋ค. ์ฃผ์ด์ง ๋ฌธ์์ด์ ๋ง์ง๋ง์ ์ฐพ๊ณ ์ ํ๋ ๋ฌธ์์ด์ด ์๊ณ ํญ์ ํด์ ์ถฉ๋์ด ์ผ์ด๋๋ ๊ฒฝ์ฐ๊ฐ ์์ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
ํ์ง๋ง, ์ผ๋ฐ์ ์ผ๋ก๋ O(NM) ๋ณด๋ค ์ ๊ฒ ์์๋๋ค.
ํด๋น ๊ธ์
๋๋๋น ๋์ '31. ๋ผ๋น ์นดํ(Rabin-Karp) ์๊ณ ๋ฆฌ์ฆ',
๋ณ์ค ๋์ 'Rabin-karp(๋ผ๋น ์นดํ) ์๊ณ ๋ฆฌ์ฆ',
๊ธฐ์ตํ๊ณ ์ถ์๊ฒ๋ค ๋ธ๋ก๊ทธ์ '[์๊ณ ๋ฆฌ์ฆ] ๋ผ๋น ์นดํ(Rabin-Karp)(๋ฌธ์์ด ํ์)(Rolling Hash)'
๋ฅผ ์ฐธ๊ณ ํ์์ต๋๋ค.
'๐ ์๊ณ ๋ฆฌ์ฆ > ๋ฌธ์์ด' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๋ณด์ด์ด-๋ฌด์ด(Boyer-Moore) ์๊ณ ๋ฆฌ์ฆ (1) | 2023.04.10 |
---|