Skip to content

Commit c675beb

Browse files
sonho00keon
authored andcommitted
Add kmp (keon#611)
* [ADD] Added KMP algorithm. * [ADD] Added test case for KMP algorithm * [EDIT] Imported KMP algorithm * [EDIT] Added KMP algorithm in README * [EDIT] Added test case for KMP algorithm * [EDIT] Edited description of algorithm with more detail * [FIX] Fixed minor bug * [EDIT] Added test case for edge cases
1 parent ee3c595 commit c675beb

File tree

4 files changed

+51
-1
lines changed

4 files changed

+51
-1
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,7 @@ If you want to uninstall algorithms, it is as simple as:
330330
- [first_unique_char](algorithms/strings/first_unique_char.py)
331331
- [repeat_substring](algorithms/strings/repeat_substring.py)
332332
- [atbash_cipher](algorithms/strings/atbash_cipher.py)
333+
- [knuth_morris_pratt](algorithms/strings/knuth_morris_pratt.py)
333334
- [tree](algorithms/tree)
334335
- [bst](algorithms/tree/bst)
335336
- [array_to_bst](algorithms/tree/bst/array_to_bst.py)

algorithms/strings/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,5 @@
3535
from .first_unique_char import *
3636
from .repeat_substring import *
3737
from .atbash_cipher import *
38+
from .knuth_morris_pratt import *
39+
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
"""
2+
Given two strings text and pattern,
3+
return the list of start indexes in text that matches with the pattern
4+
using knuth_morris_pratt algorithm.
5+
If idx is in the list, text[idx : idx + M] matches with pattern.
6+
Time complexity : O(N+M)
7+
N and M is the length of text and pattern, respectively.
8+
"""
9+
10+
def knuth_morris_pratt(text, pattern):
11+
n = len(text)
12+
m = len(pattern)
13+
pi = [0 for i in range(m)]
14+
i = 0
15+
j = 0
16+
# making pi table
17+
for i in range(1, m):
18+
while j and pattern[i] != pattern[j]:
19+
j = pi[j - 1]
20+
if pattern[i] == pattern[j]:
21+
j += 1
22+
pi[i] = j
23+
# finding pattern
24+
j = 0
25+
ret = []
26+
for i in range(n):
27+
while j and text[i] != pattern[j]:
28+
j = pi[j - 1]
29+
if text[i] == pattern[j]:
30+
j += 1
31+
if j == m:
32+
ret.append(i - m + 1)
33+
j = pi[j - 1]
34+
return ret

tests/test_strings.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@
3737
rotate,
3838
first_unique_char,
3939
repeat_substring,
40-
atbash
40+
atbash,
41+
knuth_morris_pratt
4142
)
4243

4344
import unittest
@@ -532,5 +533,17 @@ def test_atbash_cipher(self):
532533
self.assertEqual("AttaCK at DawN", atbash("ZggzXP zg WzdM"))
533534
self.assertEqual("ZggzXP zg WzdM", atbash("AttaCK at DawN"))
534535

536+
class TestKnuthMorrisPratt(unittest.TestCase):
537+
"""[summary]
538+
Test for the file knuth_morris_pratt.py
539+
540+
Arguments:
541+
unittest {[type]} -- [description]
542+
"""
543+
def test_knuth_morris_pratt(self):
544+
self.assertEqual([0, 1, 2, 3, 4], knuth_morris_pratt("aaaaaaa", "aaa"))
545+
self.assertEqual([0, 4], knuth_morris_pratt("abcdabc", "abc"))
546+
self.assertEqual([], knuth_morris_pratt("aabcdaab", "aba"))
547+
535548
if __name__ == "__main__":
536549
unittest.main()

0 commit comments

Comments
 (0)