{"componentChunkName":"component---src-templates-blog-post-js","path":"/algorithm/kmp-알고리즘-kmp-algorithm/","result":{"data":{"site":{"siteMetadata":{"title":"Bottlehs Tech Blog","description":"웹·앱·AI 개발자 전병훈(bottlehs)의 기술 블로그. AI·LLM, JavaScript·Vue, Spring Boot, 알고리즘, 블록체인 실무 가이드를 다룹니다","siteUrl":"https://www.bottlehs.dev","author":{"name":"Jeon Byung Hun","summary":"개발을 즐기는 bottlehs - Engineer, MS, AI, FE, BE, OS, IOT, Blockchain, 설계, 테스트"},"social":{"github":"bottlehs","codepen":"bottlehs"}}},"markdownRemark":{"id":"0dc0f4ef-6890-5d59-818b-8f1a94f29cf5","excerpt":"KMP 알고리즘 (Knuth-Morris-Pratt) KMP…","html":"<p><img src=\"/assets/algorithm.png\" alt=\"KMP 알고리즘 (Knuth-Morris-Pratt)\" title=\"KMP 알고리즘 (Knuth-Morris-Pratt)\"></p>\n<p>KMP는 문자열에서 패턴을 찾을 때, 이전 비교 정보를 활용해 불필요한 재비교를 피하는 알고리즘이다.</p>\n<h2 id=\"정의\" style=\"position:relative;\"><a href=\"#%EC%A0%95%EC%9D%98\" aria-label=\"정의 permalink\" class=\"anchor-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>정의</h2>\n<p>텍스트에서 패턴을 찾는 문자열 검색 알고리즘이다. 단순 문자열 검색은 불일치 시 시작 위치만 한 칸 이동해 처음부터 다시 비교하지만, KMP는 “이미 비교한 정보를 활용”해 중간까지는 맞다는 것을 알고 있으므로 그 부분만 건너뛰고 비교를 재개한다.</p>\n<p>핵심은 실패 함수(Failure Function) 또는 LPS(Longest Proper Prefix which is also Suffix) 배열이다. 각 위치에서 “자기 자신을 제외한 접두사 중 패턴의 접미사와 일치하는 가장 긴 길이”를 미리 계산해 둔다. 예를 들어 “ababa”에서 위치 4(0-based)의 LPS는 3인데, 접두사 “aba”가 접미사 “aba”와 일치하기 때문이다. 불일치 시 LPS 값을 사용해 몇 칸을 건너뛸 수 있는지 결정한다.</p>\n<h2 id=\"구현\" style=\"position:relative;\"><a href=\"#%EA%B5%AC%ED%98%84\" aria-label=\"구현 permalink\" class=\"anchor-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>구현</h2>\n<p>실패 함수는 패턴 자신을 대상으로 한 문자열 검색이다. 길이 0은 0으로 설정하고, 이후 각 위치에서 이전 LPS 값을 활용해 새 문자와 비교하며 LPS 값을 갱신한다. 일치하면 LPS를 증가시키고, 불일치면 이전 LPS 값을 이용해 다시 비교할 위치를 찾는다.</p>\n<p>문자열 검색 단계에서는 텍스트와 패턴을 비교하며, 일치하면 둘 다 다음 문자로 이동한다. 불일치 시 패턴의 LPS 값을 사용해 패턴 포인터만 적절히 이동시키고 텍스트 포인터는 유지한다. 패턴의 전체가 일치하면 매치 위치를 저장하고 패턴 포인터를 LPS 값으로 설정해 계속 검색한다.</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// 실패 함수(LPS) 구하기</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">buildLPS</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">pattern</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> m <span class=\"token operator\">=</span> pattern<span class=\"token punctuation\">.</span>length\n  <span class=\"token keyword\">const</span> lps <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Array</span><span class=\"token punctuation\">(</span>m<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">let</span> len <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> i <span class=\"token operator\">=</span> <span class=\"token number\">1</span>\n  \n  <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>i <span class=\"token operator\">&lt;</span> m<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>pattern<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span> <span class=\"token operator\">===</span> pattern<span class=\"token punctuation\">[</span>len<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      len<span class=\"token operator\">++</span>\n      lps<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> len\n      i<span class=\"token operator\">++</span>\n    <span class=\"token punctuation\">}</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>len <span class=\"token operator\">!==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        len <span class=\"token operator\">=</span> lps<span class=\"token punctuation\">[</span>len <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span>\n      <span class=\"token punctuation\">}</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">{</span>\n        lps<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token number\">0</span>\n        i<span class=\"token operator\">++</span>\n      <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span>\n  \n  <span class=\"token keyword\">return</span> lps\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token comment\">// KMP 문자열 검색</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">kmpSearch</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">text<span class=\"token punctuation\">,</span> pattern</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> n <span class=\"token operator\">=</span> text<span class=\"token punctuation\">.</span>length\n  <span class=\"token keyword\">const</span> m <span class=\"token operator\">=</span> pattern<span class=\"token punctuation\">.</span>length\n  <span class=\"token keyword\">const</span> lps <span class=\"token operator\">=</span> <span class=\"token function\">buildLPS</span><span class=\"token punctuation\">(</span>pattern<span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">const</span> result <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span>\n  \n  <span class=\"token keyword\">let</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> j <span class=\"token operator\">=</span> <span class=\"token number\">0</span> <span class=\"token comment\">// i: text, j: pattern</span>\n  \n  <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span>i <span class=\"token operator\">&lt;</span> n<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>text<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span> <span class=\"token operator\">===</span> pattern<span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      i<span class=\"token operator\">++</span>\n      j<span class=\"token operator\">++</span>\n      \n      <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>j <span class=\"token operator\">===</span> m<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        result<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span>i <span class=\"token operator\">-</span> j<span class=\"token punctuation\">)</span> <span class=\"token comment\">// 매치 위치</span>\n        j <span class=\"token operator\">=</span> lps<span class=\"token punctuation\">[</span>j <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span>      <span class=\"token comment\">// 다음 가능한 위치</span>\n      <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>j <span class=\"token operator\">!==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        j <span class=\"token operator\">=</span> lps<span class=\"token punctuation\">[</span>j <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span>\n      <span class=\"token punctuation\">}</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">{</span>\n        i<span class=\"token operator\">++</span>\n      <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span>\n  \n  <span class=\"token keyword\">return</span> result\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token comment\">// 예시 실행</span>\n<span class=\"token keyword\">const</span> text <span class=\"token operator\">=</span> <span class=\"token string\">\"ABABABCABABABCABABABC\"</span>\n<span class=\"token keyword\">const</span> pattern <span class=\"token operator\">=</span> <span class=\"token string\">\"ABABAB\"</span>\n\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token function\">buildLPS</span><span class=\"token punctuation\">(</span>pattern<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>            <span class=\"token comment\">// [0, 0, 1, 2, 3, 4]</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token function\">kmpSearch</span><span class=\"token punctuation\">(</span>text<span class=\"token punctuation\">,</span> pattern<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>     <span class=\"token comment\">// [0, 7, 14]</span>\n\n<span class=\"token comment\">// 실패 케이스</span>\n<span class=\"token keyword\">const</span> text2 <span class=\"token operator\">=</span> <span class=\"token string\">\"ABCDEFG\"</span>\n<span class=\"token keyword\">const</span> pattern2 <span class=\"token operator\">=</span> <span class=\"token string\">\"XYZ\"</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token function\">kmpSearch</span><span class=\"token punctuation\">(</span>text2<span class=\"token punctuation\">,</span> pattern2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>   <span class=\"token comment\">// []</span></code></pre></div>\n<h2 id=\"데모\" style=\"position:relative;\"><a href=\"#%EB%8D%B0%EB%AA%A8\" aria-label=\"데모 permalink\" class=\"anchor-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>데모</h2>\n<p><a href=\"https://codepen.io/pen/?template=yLgbWPj\">https://codepen.io/pen/?template=yLgbWPj</a></p>","tableOfContents":"<ul>\n<li><a href=\"/algorithm/kmp-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-kmp-algorithm/#%EC%A0%95%EC%9D%98\">정의</a></li>\n<li><a href=\"/algorithm/kmp-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-kmp-algorithm/#%EA%B5%AC%ED%98%84\">구현</a></li>\n<li><a href=\"/algorithm/kmp-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-kmp-algorithm/#%EB%8D%B0%EB%AA%A8\">데모</a></li>\n</ul>","wordCount":{"words":194},"fields":{"slug":"/algorithm/kmp-알고리즘-kmp-algorithm/","image":"/assets/algorithm.png","faq":[]},"frontmatter":{"title":"KMP 알고리즘 (Knuth-Morris-Pratt)","date":"2025년 11월 1일","dateISO":"2025-11-01T00:00:00.000Z","updatedISO":null,"category":"algorithm","description":"문자열 검색을 효율적으로 수행하는 알고리즘. 실패 함수(Failure Function)를 이용해 불필요한 비교를 건너뛰며, 시간복잡도는 O(N+M)이다.","tags":["KMP 알고리즘","Knuth-Morris-Pratt","문자열 검색","알고리즘","Algorithm","JavaScript"]}}},"pageContext":{"slug":"/algorithm/kmp-알고리즘-kmp-algorithm/","previous":{"fields":{"slug":"/algorithm/벨만-포드-bellman-ford/"},"frontmatter":{"title":"벨만-포드 알고리즘 (Bellman-Ford)","tags":["벨만-포드","Bellman-Ford","최단 경로","알고리즘","Algorithm","JavaScript"]}},"next":{"fields":{"slug":"/ai/채팅GPT의-비밀-공개-LLM이-당신과-대화하는-진짜-원리/"},"frontmatter":{"title":"채팅GPT의 비밀 공개 LLM이 당신과 대화하는 진짜 원리","tags":["LLM","Large Language Model","트랜스포머","Transformer","인공지능","AI","채팅GPT","딥러닝"]}}}},"staticQueryHashes":["213619243","3262363727"]}