๐Ÿ“š KMP ์•Œ๊ณ ๋ฆฌ์ฆ˜

๐Ÿ“š KMP ์•Œ๊ณ ๋ฆฌ์ฆ˜

  • ๋ฌธ์ž์—ด ๊ฒ€์ƒ‰ ์•Œ๊ณ ๋ฆฌ์ฆ˜
  • ํ…์ŠคํŠธ ๋‚ด์—์„œ ํŒจํ„ด ๋ฌธ์ž์—ด์„ ๋น ๋ฅด๊ฒŒ ์ฐพ๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜
  • ์ผ๋ฐ˜์ ์ธ ๋ฌธ์ž์—ด ํƒ์ƒ‰(๋ธŒ๋ฃจํŠธํฌ์Šค)์ด (O(n*m)) ์ธ ๋ฐ˜๋ฉด KMP๋Š” (O(n+m)) ์‹œ๊ฐ„์— ์ˆ˜ํ–‰ํ•œ๋‹ค.(n = ํ…์ŠคํŠธ ๊ธธ์ด, m = ํŒจํ„ด ๊ธธ์ด)
  • KMP๋ฅผ ์ž˜ ์ •๋ฆฌํ•ด์ค€ ์‚ฌ์ดํŠธ

๐Ÿ”Ž KMP ํ•ต์‹ฌ ์•„์ด๋””์–ด

  • ํŒจํ„ด ๋‚ด์—์„œ ์‹คํŒจํ•  ๋•Œ ๋‹ค์‹œ ์ฒ˜์Œ๋ถ€ํ„ฐ ๋น„๊ตํ•˜์ง€ ์•Š๊ณ , ์ด๋ฏธ ์ผ์น˜ํ–ˆ๋˜ ๋ถ€๋ถ„์„ ํ™œ์šฉํ•ด ๊ฑด๋„ˆ๋›ด๋‹ค.
  • ์ด๋ฅผ ์œ„ํ•ด ์ ‘๋‘์‚ฌ-์ ‘๋ฏธ์‚ฌ ์ผ์น˜ ์ •๋ณด ๋ฅผ ๋ฏธ๋ฆฌ ๊ณ„์‚ฐํ•˜๋Š” ๊ณผ์ •์ด ํ•„์š”ํ•˜๋‹ค.
  • ์ด๋ฅผ lps[] ๋ฐฐ์—ด์ด๋ผ ๋ถ€๋ฅธ๋‹ค(Longest Prefix Seffix)

๐Ÿš€ KMP ๋‹จ๊ณ„๋ณ„ ์„ค๋ช…

  1. lps ๋ฐฐ์—ด ๋ฐ˜๋“ค๊ธฐ
    1. lps[i]๋Š” ํŒจํ„ด์˜ 0 ~ i ๊นŒ์ง€ ๋ถ€๋ถ„ ๋ฌธ์ž์—ด์—์„œ ์ ‘๋‘์‚ฌ์™€ ์ ‘๋ฏธ์‚ฌ๊ฐ€ ์ผ์น˜ํ•˜๋Š” ๊ฐ€์žฅ ๊ธด ๊ธธ์ด๋ฅผ ๋œปํ•œ๋‹ค.
    2. ex) ํŒจํ„ด : โ€œABABCโ€, lps ๋ฐฐ์—ด : [0, 0, 1, 2, 0]
  2. ๋ฌธ์ž์—ด ํƒ์ƒ‰
    1. ํ…์ŠคํŠธ์™€ ํŒจํ„ด์„ ์ˆœํšŒํ•˜๋ฉฐ ์ผ์น˜ ์—ฌ๋ถ€ ๊ฒ€์‚ฌ
    2. ๋ถˆ์ผ์น˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ํŒจํ„ด์—์„œ ๋ฐ”๋กœ ์ด์ „ lps๊ฐ’์„ ์ฐธ์กฐํ•ด ๋น„๊ต๋ฅผ ๊ณ„์†ํ•จ์œผ๋กœ์จ ๋ถˆํ•„์š”ํ•œ ๋ฐ˜๋ณต ๋ฐฉ์ง€

๐Ÿ’ป KMP ๊ตฌํ˜„

#include <iostream>
#include <vector>
#include <string>

using namespace std;

// 1. lps ๋ฐฐ์—ด ๊ณ„์‚ฐ ํ•จ์ˆ˜
vector<int> computeLps(const string& pattern) {
    int m = pattern.size();
    vector<int> lps(m, 0);

    int len = 0; // ํ˜„์žฌ๊นŒ์ง€์˜ ์ ‘๋‘์‚ฌ - ์ ‘๋ฏธ์‚ฌ ์ตœ๋Œ€ ๊ธธ์ด
    int i = 1; // lps[0]์€ ํ•ญ์ƒ 0์ด๋ฏ€๋กœ i = 1๋ถ€ํ„ฐ ์‹œ์ž‘

    while(i < m)
    {
        if(pattern[i] == patter[len])
        {
            len++;
            lps[i] = len;
            i++;
        }
        else
        {
            if(len != 0)
            {
                len = lps[len-1]; // len์„ lps[len-1]๋กœ ์ค„์—ฌ์„œ ๋‹ค์‹œ ๋น„๊ต
            }
            else
            {
                lps[i] = 0;
                i++;
            }
        }
    }return lps;
}


// 2. KMP ๊ฒ€์ƒ‰ ํ•จ์ˆ˜ : ํŒจํ„ด์ด ํ…์ŠคํŠธ์— ์žˆ๋Š”์ง€ ํ™•์ธ
bool KMP(const string& text, const string& pattern) {
    int n = text.size();
    int m = pattern.size();

    if(m == 0)  return true; // ๋นˆ ํŒจํ„ด์€ ํ•ญ์ƒ ์กด์žฌํ•จ
    
    vector<int> lps = coputeLps(pattern);

    int i = 0; // ํ…์ŠคํŠธ ์ธ๋ฑ์Šค
    int j = 0; // ํŒจํ„ด ์ธ๋ฑ์Šค

    while(i < n)
    {
        if(text[i] == pattern[j])
        {
            i++;
            j++;

            if(j == m)
            {
                // ํŒจํ„ด ์ „๋ถ€ ์ผ์น˜
                return true;
                // j = lps[j-1]; // ์—ฌ๋Ÿฌ๊ฐœ ์ฐพ์œผ๋ ค๋ฉด ์—ฌ๊ธฐ์„œ ๊ณ„์† ์ง„ํ–‰
            }
        }
        else
        {
            if(j != 0)
            {
                j = lps[j-1];
            }
            else
            {
                i++;
            }
        }
    }
    return false; // ํŒจํ„ด์—†์Œ
}

๐Ÿ“Œ ์š”์•ฝ

  • KMP ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ž‘์„ฑ์—๋Š” 2๊ฐ€์ง€ ๋‹จ๊ณ„๊ฐ€ ์กด์žฌํ•œ๋‹ค.
    1. computeLps - ํŒจํ„ด์—์„œ ์ ‘๋‘์‚ฌ-์ ‘๋ฏธ์‚ฌ ์ผ์น˜ ๊ธธ์ด ๊ณ„์‚ฐ
    2. KMP - ํ…์ŠคํŠธ ๋‚ด์—์„œ ํŒจํ„ด ๊ฒ€์ƒ‰
  • lps ๋ฐฐ์—ด์€ ๋ถˆ์ผ์น˜ ์‹œ ์ด๋™ํ•  ์œ„์น˜๋ฅผ ๋ฏธ๋ฆฌ ๊ณ„์‚ฐํ•ด ์‹œ๊ฐ„ ๋‚ญ๋น„๋ฅผ ๋ฐฉ์ง€ํ•œ๋‹ค.
  • ์ „์ฒด ํƒ์ƒ‰์ด (O(n+m)) ์— ์ˆ˜ํ–‰๋œ๋‹ค.