๋ฌธ์์ด ์๊ณ ๋ฆฌ์ฆ - KMP ์๊ณ ๋ฆฌ์ฆ
KMP(Knuth-Morris-Pratt) ์๊ณ ๋ฆฌ์ฆ
- ๋ถ์ผ์น๊ฐ ๋ฐ์ํ ํ ์คํธ ๋ฌธ์์ด์ ์ ๋ถ๋ถ์ ๋ค์ ๋น๊ตํ์ง ์๊ณ ์ผ์นํ๋ ๋ถ๋ถ ๋ฌธ์์ด๋ถํฐ ๋งค์นญ์ ์ํํจ์ผ๋ก์จ ๋ฌธ์์ด ๋น๊ต ํ์๋ฅผ ๋ํญ ๊ฐ์์ํจ ์๊ณ ๋ฆฌ์ฆ
-
ํ๊ฒ ๋ฌธ์์ด์ ๋์์ผ๋ก
๋ถ๋ถ ์ผ์น ํ ์ด๋ธ
์ ์์ฑํ์ฌ ํ๊ฒ ๋ฌธ์์ด ๋ด๋ถ์์ ์ค๋ณต๋๋ ๋ฌธ์์ด์ ๋น ๋ฅด๊ฒ ์ฐพ์- ํ๊ฒ ๋ฌธ์์ด์ 1๋ฒ ์ธ๋ฑ์ค ๋ฌธ์๋ถํฐ ๋ง์ง๋ง ์ธ๋ฑ์ค ๋ฌธ์๊น์ง ํ์ธํ๋ฉฐ ๊ฐ ์ธ๋ฑ์ค ๋ฌธ์๋ฅผ ์ถ๊ฐํ ๋ถ๋ถ๋ฌธ์์ด์ ์ ๋์ฌ์ ์ ๋ฏธ์ฌ๊ฐ ์ผ์นํ๋ ์ต๋ ๊ธธ์ด๋ฅผ ์ ์ฅ
- ๋ถ๋ถ ์ผ์น ํ ์ด๋ธ์ ์ด์ฉํด ์ฃผ์ด์ง ๋ฌธ์์ด๊ณผ ํ๊ฒ ๋ฌธ์์ด์ ๋น๊ตํด ๋งค์นญ์ด ์คํจํ์ ๋ ํ๊ฒ ๋ฌธ์์ด ํฌ์ธํฐ๊ฐ ๋์๊ฐ ์ธ๋ฑ์ค๋ฅผ ์ฐพ์ ์ ์์
- ์ฃผ์ด์ง ๋ฌธ์์ด ๊ธธ์ด๊ฐ M์ด๊ณ ํ๊ฒ ๋ฌธ์์ด ๊ธธ์ด๊ฐ N์ผ ๋ O(M+N)์ ์๊ฐ๋ณต์ก๋๋ก ์ผ์นํ๋ ํ๊ฒ ๋ฌธ์์ด์ ์ฐพ์ ์ ์๋ค.
๊ตฌํ
Java
public class KMPTest {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
char[] text = br.readLine().toCharArray(); // ํ๊ฒ ๋ฌธ์์ด์ ์ฐพ์์ผํ๋ ์ฃผ์ด์ง ๋ฌธ์์ด
char[] target = br.readLine().toCharArray(); // ํ๊ฒ ๋ฌธ์์ด
int textLen = text.length, targetLen = target.Length;
int[] subPattern = new int[targetLen]; // ๋ถ๋ถ ์ผ์น ํ
์ด๋ธ
// ๋ถ๋ถ ์ผ์น ํ
์ด๋ธ ์์ฑ
for (int i=1, j=0; i<targetLen; i++) { // i : ์ ๋ฏธ์ฌ ํฌ์ธํฐ, j : ์ ๋์ฌ ํฌ์ธํฐ
while (j>0 && target[i]!=target[j]) j = subPattern[j-1]; // ๋ฌธ์์ด์ด j์์ ๋ฌ๋ผ์ง๋ค๋ ๊ฒ์ (j-1)๊น์ง ์ผ์นํ์์ ์๋ฏธํ๋ฏ๋ก ๋ถ๋ถ ์ผ์น ํ
์ด๋ธ์ (j-1)์ธ๋ฑ์ค๋ฅผ ํ์ธ
if (target[i]==target[j]) subPattern[i] = ++j; // (j+1) ๊ธธ์ด๋งํผ ์ค๋ณต๋๋ฏ๋ก ์ด๋ฅผ ๋ถ๋ถ์ผ์นํ
์ด๋ธ์ ์ ์ฅํ๊ณ , ๋ค์ ๋น๊ต๋ฅผ ์ํด j์ธ๋ฑ์ค ์ฆ๊ฐ -> ++j
}
int cnt = 0;
List<Integer> patternIdx = new ArrayList<Integer>();
// ์ฃผ์ด์ง ๋ฌธ์์ด๊ณผ ํ๊ฒ ๋ฌธ์์ด์ ๋น๊ตํ๋ฉฐ ์ผ์นํ๋์ง ํ์ธ
for (int i=0, j=0; i<textLen; i++) { // i : ํ
์คํธ ํฌ์ธํฐ , j: ํจํด ํฌ์ธํฐ
while(j>0 && text[i]!=target[j]) j = subPattern[j-1]; // ๋ฌธ์์ด์ด j์์ ๋ฌ๋ผ์ง๋ค๋ ๊ฒ์ (j-1)๊น์ง ์ผ์นํ์์ ์๋ฏธํ๋ฏ๋ก ๋ถ๋ถ ์ผ์น ํ
์ด๋ธ์ (j-1)์ธ๋ฑ์ค๋ฅผ ํ์ธ
if (text[i]==target[j]){ // ์ฃผ์ด์ง ๋ฌธ์์ด์ ๋ฌธ์์ ํ๊ฒ ๋ฌธ์์ด ๋ฌธ์๊ฐ ์ผ์นํ ๋
if (j==(targetLen-1)) { // ๋ง์ฝ ํ๊ฒ ๋ฌธ์์ด์ ๋ง์ง๋ง ๋ฌธ์๊น์ง ์ผ์นํ๋ค๋ฉด ํ๊ฒ ๋ฌธ์์ด์ ์ฐพ์์์ ์๋ฏธ
cnt++; // ์ผ์นํ๋ ๋ฌธ์์ด ๊ฐ์ ์ฆ๊ฐ
patternIdx.add((i+1) - targetLen); // ์ผ์นํ๋ ๋ฌธ์์ด์ด ์กด์ฌํ๋ ์์น ์ ์ฅ
j = subPattern[j]; // j๊น์ง ์ผ์นํ์ผ๋ฏ๋ก ๋ถ๋ถ ์ผ์น ํ
์ด๋ธ์ j์ธ๋ฑ์ค๋ฅผ ํ์ธ
} else ++j; // j๊ฐ ํจํด์ ์ค๊ฐ ์ธ๋ฑ์ค์ด๋ฏ๋ก ์์ง ๋ค์ฌ๋ค๋ด์ผํ ํจํด ์ธ๋ฑ์ค๊ฐ ๋จ์
}
}
}
}