written by sohyeon, hyemin ๐ก
์ด๋ค ๋ฌธ์์ด ์์ ํ์ํ๊ณ ์ ํ๋ ๋ฌธ์์ด์ด ๋ค์ด ์๋์ง ์กฐ์ฌํ๊ณ ๊ทธ ์์น๋ฅผ ์ฐพ์๋ด๋ ๊ฒ์ด๋ค.
ํ์ํ ๋ฌธ์์ด์ ํจํด
์ด๋ค ๋ฌธ์์ด์ ์๋ณธ ํ
์คํธ
๋ผ๊ณ ํํํ๊ฒ ๋ค.
์ ํ ๊ฒ์์ ํ์ฅํ ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ๊ฐ๋ฅํ ๋ชจ๋ ๊ฒฝ์ฐ์ ๋ํด ๋ชจ๋ ์ง์ ํด ๋ณด๋ ์๊ณ ๋ฆฌ์ฆ์ด๋ค.
๊ฐ์ฅ ๋จ์ํ ๋ฌธ์์ด ํ์ ๋ฐฉ๋ฒ์ผ๋ก ๋จ์๋ฒ, ์๋ฐ๋ฒ์ด๋ผ๊ณ ๋ ํ๋ค.
๋ฌธ์์ด ํ์์ ๋ธ๋ฃจํธ-ํฌ์ค
๋ฅผ ์ ์ฉํ ๊ฒฝ์ฐ
-
ํจํด์ ํ ์คํธ์ ์ฒซ๋ฌธ์๋ถํฐ ๊ฒน์น๋ ํ์ธ
- ๋ชจ๋ ํจํด์ด ์ผ์นํ ๊ฒฝ์ฐ ํ์ ์ฑ๊ณต
-
ํจํด๊ณผ ๋ค๋ฅธ ๋ฌธ์๊ฐ ๋ํ๋๋ฉด ๊ฒ์์ ์ค๋จ
-
ํ ์คํธ์ ๊ฒ์ฌ ์์น๋ฅผ 1์นธ ์ฎ๊ฒจ ํ์ ์งํ
- ๋ชจ๋ ํจํด์ด ์ผ์นํ ๊ฒฝ์ฐ ํ์ ์ฑ๊ณต
- ๋ค๋ฅธ ๋ฌธ์๊ฐ ๋ํ๋๋ฉด 3์ ๊ณผ์ ์ ๋ฐ๋ณต
์ํ ์๊ฐ ๋ฉด์์ ๋นํจ์จ์ ์ธ ์๊ณ ๋ฆฌ์ฆ์ด๋ค.
๋ธ๋ฃจํธ-ํฌ์ค๋ฒ์ผ๋ก ๋ฌธ์์ด์ ๊ฒ์ํ๋ ํ๋ก๊ทธ๋จ
import java.util.Scanner;
class BFmatch {
// ๋ธ๋ฃจํธ-ํฌ์ค๋ฒ์ผ๋ก ๋ฌธ์์ด์ ๊ฒ์ํ๋ ๋ฉ์๋
static int bfMatch(String txt, String pat) {
int pt = 0; // txt ์ปค์
int pp = 0; // pat ์ปค์
while (pt != txt.length() && pp != pat.length()) {
if (txt.charAt(pt) == pat.charAt(pp)) {
pt++;
pp++;
} else {
pt = pt - pp + 1;
pp = 0;
}
}
if (pp == pat.length()) // ๊ฒ์ ์ฑ๊ณต!
return pt - pp;
return -1; // ๊ฒ์ ์คํจ!
}
public static void main(String[] args) {
Scanner stdIn = new Scanner(System.in);
System.out.print("ํ
์คํธ๏ผ");
String s1 = stdIn.next(); // ํ
์คํธ์ฉ ๋ฌธ์์ด
System.out.print("ํจํด๏ผ");
String s2 = stdIn.next(); // ํจํด์ฉ ๋ฌธ์์ด
int idx = bfMatch(s1, s2); // ๋ฌธ์์ด s1์์ ๋ฌธ์์ด s2๋ฅผ ๊ฒ์
if (idx == -1)
System.out.println("ํ
์คํธ์ ํจํด์ด ์์ต๋๋ค.");
else {
// ์ผ์นํ๋ ๋ฌธ์ ๋ฐ๋ก ์๊น์ง์ ๊ธธ์ด๋ฅผ ๊ตฌํฉ๋๋ค.
int len = 0;
for (int i = 0; i < idx; i++)
len += s1.substring(i, i + 1).getBytes().length;
len += s2.length();
System.out.println((idx + 1) + "๋ฒ์งธ ๋ฌธ์๋ถํฐ ์ผ์นํฉ๋๋ค.");
System.out.println("ํ
์คํธ๏ผ" + s1);
System.out.printf(String.format("ํจํด๏ผ%%%ds\n", len), s2);
}
}
}
- ํ ์คํธ์์ ํจํด์ ๊ฒ์ํ์ฌ ํ ์คํธ์ ์์น๋ฅผ ๋ฐํํ๋ค.
- ํ
์คํธ์ ํจํด์ด ์ฌ๋ฌ๊ฐ ์๋ ๊ฒฝ์ฐ ๊ฐ์ฅ ์์ชฝ์ ์์นํ ํ
์คํธ์ ์ธ๋ฑ์ค๋ฅผ ๋ฐํํ๊ณ ,
๊ฒ์์ ์คํจํ๋ฉด -1์ ๋ฐํํ๋ค.
๋ธ๋ฃจํธ-ํฌ์ค๋ณด๋ค ํจ์จ์ ์ด๊ฒ ๋ฌธ์์ด์ ํ์ํ๋ ์๊ณ ๋ฆฌ์ฆ์ด๋ค.
KMP
๋ ๊ฒ์ฌํ๋ ์์น ๊ฒฐ๊ณผ๋ฅผ ํ์ฉํ๋ ์๊ณ ๋ฆฌ์ฆ์ด๋ค.
KMP
๋ ์์ ๋ฅผ ๋ณด๋ ๊ฒ์ด ์ดํดํ๊ธฐ ์ฝ๋ค.
ํ
์คํธ ZABCABXACCADEF
์์ ํจํด ABCABD
๋ฅผ ๊ฒ์ํ๋ ์์
ํจํด์ ํ
ABCABD
-00120
0123456789
ํ
์คํธ ZABCABXACC
ํจํด ABCABD
x
์ฒซ๋ฒ์งธ ๋ฌธ์์ ํจํด์ด ์ผ์นํ์ง ์๋๋ค 1์นธ ๋ค๋ก ์ด๋์์ผ ํ์ํ๋ค.
0123456789
ํ
์คํธ ZABCABXACC
ํจํด ABCABD
ooooox
ํจํด์ D๊ฐ ์ผ์นํ์ง ์๋๋ค.
์์ ํ๋ฅผ ๋ณด๋ฉด ํจํด์ ๊ฒน์น๋ ๋ถ๋ถ์ด ์กด์ฌํ๋ฉฐ AB๊น์ง๋ ํจํด๊ณผ ํ
์คํธ๊ฐ ์ผ์นํ๋ค.
ํด๋น ์ธ๋ฑ์ค๋ก ์ด๋ํด ํ์ํ๋ค.
0123456789
ํ
์คํธ ZABCABXACC
ํจํด ABCABD
oox
๋์ด์ ์ด๋ ๋ถ๊ฐ ํ์ ์คํจ
ํจํด์ ํ์นธ์ฉ ์ด๋ํ์ง ์๊ณ ํจํด์ ๊ฒน์น๋ ๋ถ๋ถ์ ์ฐพ์๋ด ๋ค์ ์์ํ ์์น๋ฅผ ๊ตฌํ๋ค.
ํจํด์ ์ต์ํ๋ง ์ด๋์์ผ ํจ์จ์ ๋์ธ๋ค.
๋ช๋ฒ์งธ ๋ฌธ์๋ถํฐ ๋ค์ ๊ฒ์ํ ์ง ๊ตฌํ๊ธฐ ์ํ ํ๋ฅผ ๋ง๋ค์ด ๊ณ์ฐํ๋ค.
import java.util.Scanner;
// KMP๋ฒ์ ์ํ ๋ฌธ์์ด ๊ฒ์
class KMPmatch {
// KMP๋ฒ์ ์ํ ๋ฌธ์์ด ๊ฒ์
static int kmpMatch(String txt, String pat) {
int pt = 1; // txt ์ปค์
int pp = 0; // pat ์ปค์
int[] skip = new int[pat.length() + 1]; // ๊ฑด๋๋ฐ๊ธฐ ํ
// ๊ฑด๋๋ฐ๊ธฐ ํ๋ฅผ ๋ง๋ญ๋๋ค.
skip[pt] = 0;
while (pt != pat.length()) {
if (pat.charAt(pt) == pat.charAt(pp))
skip[++pt] = ++pp;
else if (pp == 0)
skip[++pt] = pp;
else
pp = skip[pp];
}
// ๊ฒ์
pt = pp = 0;
while (pt != txt.length() && pp != pat.length()) {
if (txt.charAt(pt) == pat.charAt(pp)) {
pt++;
pp++;
} else if (pp == 0)
pt++;
else
pp = skip[pp];
}
if (pp == pat.length()) // pt - pp๋ฅผ ๋ฐํํฉ๋๋ค.
return pt - pp;
return -1; // ๊ฒ์ ์คํจ
}
public static void main(String[] args) {
Scanner stdIn = new Scanner(System.in);
System.out.print("ํ
์คํธ๏ผ");
String s1 = stdIn.next(); // ํ
์คํธ์ฉ ๋ฌธ์์ด
System.out.print("ํจํด๏ผ");
String s2 = stdIn.next(); // ํจํด์ฉ ๋ฌธ์์ด
int idx = kmpMatch(s1, s2); // ๋ฌธ์์ด s1์์ ๋ฌธ์์ด s2๋ฅผ ๋ธ๋ฃจํธ-ํฌ์ค๋ฒ์ผ๋ก ๊ฒ์
if (idx == -1)
System.out.println("ํ
์คํธ์ ํจํด์ด ์์ต๋๋ค.");
else {
int len = 0;
for (int i = 0; i < idx; i++)
len += s1.substring(i, i + 1).getBytes().length;
len += s2.length();
System.out.println((idx + 1) + "๋ฒ์งธ ๋ฌธ์์ ์ผ์นํฉ๋๋ค.");
System.out.println("ํ
์คํธ๏ผ" + s1);
System.out.printf(String.format("ํจํด๏ผ%%%ds\n", len), s2);
}
}
}
KMP๋ณด๋ค ํจ์จ์ด ์ฐ์ํด ์ค์ ๋ก ๋ฌธ์์ด ํ์์ ๋ง์ด ์ฌ์ฉ๋๋ ์๊ณ ๋ฆฌ์ฆ์ด๋ค.
ํจํด์ ๋ง์ง๋ง ๋ฌธ์๋ถํฐ ์์ชฝ์ผ๋ก ๊ฒ์ฌ๋ฅผ ์งํํ๋ฉด์
์ผ์นํ์ง ์๋ ๋ฌธ์๊ฐ ์์ผ๋ฉด ๋ฏธ๋ฆฌ ์ค๋นํ ํ์ ๋ฐ๋ผ ํจํด์ ์ฎ๊ธธ ํฌ๊ธฐ๋ฅผ ์ ํ๋ค.
ABCXDEZCABACABAC
์์ ํจํดABAC
๋ฅผ ๊ฒ์ํ๋ ๊ฒฝ์ฐ
v
ํ
์คํธ ABC X DEZCABACABAC
a ABA C ํจํด๊ณผ ํ
์คํธ์ ๋ฌธ์๊ฐ ์๋ก ๋ค๋ฆ
b AB A C ํจํด์ 1์นธ ์ฎ๊ฒจ๋ ๋ฌธ์๊ฐ ์๋ก ๋ค๋ฅด๋ค.
c A B AC ํจํด์ 2์นธ ์ฎ๊ฒจ๋ ๋ฌธ์๊ฐ ์๋ก ๋ค๋ฅด๋ค.
d A BAC ํจํด์ 3์นธ ์ฎ๊ฒจ๋ ๋ฌธ์๊ฐ ์๋ก ๋ค๋ฅด๋ค.
ํจํด์์ ๋ค์ด์์ง ์์ ํ
์คํธ๋ฅผ ๋ฐ๊ฒฌํ๋ฉด ํด๋น ์์น๊น์ง ๊ฑด๋๋ฐ๊ณ ํ์์ ์ํํ๋ค.
v
ํ
์คํธ ABCXDEZ C ABACABAC
ABA C ์ผ์น
v
ํ
์คํธ ABCXDE Z CABACABAC
a ABA C
b AB A C
c A B AC
d A BAC ๋ถ์ผ์น
Z๊ฐ ํจํด์ ์กด์ฌํ์ง ์์ผ๋ฏ๋ก ํ๋ฒ์ 3์นธ ์ฎ๊ฒจ ๋ค์ ํ์ํ๋ค.
v
ํ
์คํธ ABCXDEZCAB A CABAC
a ABA C
b AB A C ์ผ์น
A ๋ฌธ์๊ฐ ์ผ์นํ๋ ๊ฒ์ ํ์ธํ๊ณ
ํด๋น ์์น์์ ํจํด์ ๋ง์ง๋ง ์์น ๋ฌธ์๋ถํฐ ๋น๊ตํ๋ค.
<---
ํ
์คํธ ABCXDEZC ABAC ABAC
ABAC ์ผ์น
๋ชจ๋ ์ผ์นํ์ฌ ๊ฒ์์ ์ฑ๊ณตํ๋ค.
ํจํด์ ๊ธธ์ด๋ฅผ n์ด๋ผ๊ณ ํ๋ฉด ํ์ฌ ๊ฒ์ฌํ๊ณ ์๋ ํ
์คํธ์ ๋ฌธ์ ์์น๋ก๋ถํฐ
๋ค์์ ๊ฒ์ฌํ ํจํด์ ๋ง์ง๋ง ๋ฌธ์ ์์น๊ฐ n๋งํผ ๋จ์ด์ง ์ ์๋๋ก ํจํด์ ์ด๋ ์ํจ๋ค.
๊ฐ๊ฐ์ ๋ฌธ์๋ฅผ ๋ง๋ฌ์ ๋ ํจํด์ ์ฎ๊ธธ ํฌ๊ธฐ๋ฅผ ์ ์ฅํ ํ๋ฅผ ๋ง๋ค์ด์ผ ํ๋ค.
n = ํจํด ๋ฌธ์์ด์ ๊ธธ์ด
-
ํจํด์ ๋ค์ด ์์ง ์์ ๋ฌธ์๋ฅผ ๋ง๋ ๊ฒฝ์ฐ
- ํจํด์ ์ฎ๊ธธ ํฌ๊ธฐ๋ n์ด๋ค.
-
ํจํด์ ๋ค์ด ์๋ ๋ฌธ์๋ฅผ ๋ง๋ ๊ฒฝ์ฐ
- ๋ง์ง๋ง์ ๋์ค๋ ์์น์ ์ธ๋ฑ์ค๊ฐ k์ด๋ฉด ํจํด์ ์ฎ๊ธธ ํฌ๊ธฐ๋ n-k-1์ด๋ค.
- ๊ฐ์ ๋ฌธ์๊ฐ ํจํด ์์ ์ค๋ณตํด์ ๋ค์ด์์ง ์๋ค๋ฉด ํจํด์ ์ฎ๊ธธ ํฌ๊ธฐ๋ n์ด๋ค.
import java.util.Scanner;
class BMmatch {
// Boyer-Moore๋ฒ์ผ๋ก ๋ฌธ์์ด์ ๊ฒ์
static int bmMatch(String txt, String pat) {
int pt; // txt ์ปค์
int pp; // pat ์ปค์
int txtLen = txt.length(); // txt์ ๋ฌธ์ ๊ฐ์
int patLen = pat.length(); // pat์ ๋ฌธ์ ๊ฐ์
int[] skip = new int[Character.MAX_VALUE + 1]; // ๊ฑด๋๋ฐ๊ธฐ ํ
// ๊ฑด๋๋ฐ๊ธฐ ํ ๋ง๋ค๊ธฐ
for (pt = 0; pt <= Character.MAX_VALUE; pt++)
skip[pt] = patLen;
for (pt = 0; pt < patLen - 1; pt++)
skip[pat.charAt(pt)] = patLen - pt - 1; // pt == patLen - 1
// ๊ฒ์
while (pt < txtLen) {
pp = patLen - 1; // pat์ ๋ ๋ฌธ์์ ์ฃผ๋ชฉ
while (txt.charAt(pt) == pat.charAt(pp)) {
if (pp == 0)
return pt; // ๊ฒ์ ์ฑ๊ณต
pp--;
pt--;
}
pt += (skip[txt.charAt(pt)] > patLen - pp) ? skip[txt.charAt(pt)] : patLen - pp;
}
return -1; // ๊ฒ์ ์คํจ
}
public static void main(String[] args) {
Scanner stdIn = new Scanner(System.in);
System.out.print("ํ
์คํธ๏ผ");
String s1 = stdIn.next(); // ํ
์คํธ์ฉ ๋ฌธ์์ด
System.out.print("ํจํด๏ผ");
String s2 = stdIn.next(); // ํจํด์ฉ ๋ฌธ์์ด
int idx = bmMatch(s1, s2); // ๋ฌธ์์ด s1์์ ๋ฌธ์์ด s2๋ฅผ BM๋ฒ์ผ๋ก ๊ฒ์
if (idx == -1)
System.out.println("ํ
์คํธ์ ํจํด์ด ์์ต๋๋ค.");
else {
int len = 0;
for (int i = 0; i < idx; i++)
len += s1.substring(i, i + 1).getBytes().length;
len += s2.length();
System.out.println((idx + 1) + "๋ฒ์งธ ๋ฌธ์์ ์ผ์นํฉ๋๋ค.");
System.out.println("ํ
์คํธ๏ผ" + s1);
System.out.printf(String.format("ํจํด๏ผ%%%ds\n", len), s2);
}
}
}
Do it! ์๋ฃ๊ตฌ์กฐ์ ํจ๊ป ๋ฐฐ์ฐ๋ ์๊ณ ๋ฆฌ์ฆ ์ ๋ฌธ, ์๋ฐ ํธ