Skip to content

Commit

Permalink
Add kmp (keon#611)
Browse files Browse the repository at this point in the history
* [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
  • Loading branch information
sonho00 authored and keon committed Dec 11, 2019
1 parent ee3c595 commit c675beb
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ If you want to uninstall algorithms, it is as simple as:
- [first_unique_char](algorithms/strings/first_unique_char.py)
- [repeat_substring](algorithms/strings/repeat_substring.py)
- [atbash_cipher](algorithms/strings/atbash_cipher.py)
- [knuth_morris_pratt](algorithms/strings/knuth_morris_pratt.py)
- [tree](algorithms/tree)
- [bst](algorithms/tree/bst)
- [array_to_bst](algorithms/tree/bst/array_to_bst.py)
Expand Down
2 changes: 2 additions & 0 deletions algorithms/strings/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,5 @@
from .first_unique_char import *
from .repeat_substring import *
from .atbash_cipher import *
from .knuth_morris_pratt import *

34 changes: 34 additions & 0 deletions algorithms/strings/knuth_morris_pratt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"""
Given two strings text and pattern,
return the list of start indexes in text that matches with the pattern
using knuth_morris_pratt algorithm.
If idx is in the list, text[idx : idx + M] matches with pattern.
Time complexity : O(N+M)
N and M is the length of text and pattern, respectively.
"""

def knuth_morris_pratt(text, pattern):
n = len(text)
m = len(pattern)
pi = [0 for i in range(m)]
i = 0
j = 0
# making pi table
for i in range(1, m):
while j and pattern[i] != pattern[j]:
j = pi[j - 1]
if pattern[i] == pattern[j]:
j += 1
pi[i] = j
# finding pattern
j = 0
ret = []
for i in range(n):
while j and text[i] != pattern[j]:
j = pi[j - 1]
if text[i] == pattern[j]:
j += 1
if j == m:
ret.append(i - m + 1)
j = pi[j - 1]
return ret
15 changes: 14 additions & 1 deletion tests/test_strings.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
rotate,
first_unique_char,
repeat_substring,
atbash
atbash,
knuth_morris_pratt
)

import unittest
Expand Down Expand Up @@ -532,5 +533,17 @@ def test_atbash_cipher(self):
self.assertEqual("AttaCK at DawN", atbash("ZggzXP zg WzdM"))
self.assertEqual("ZggzXP zg WzdM", atbash("AttaCK at DawN"))

class TestKnuthMorrisPratt(unittest.TestCase):
"""[summary]
Test for the file knuth_morris_pratt.py
Arguments:
unittest {[type]} -- [description]
"""
def test_knuth_morris_pratt(self):
self.assertEqual([0, 1, 2, 3, 4], knuth_morris_pratt("aaaaaaa", "aaa"))
self.assertEqual([0, 4], knuth_morris_pratt("abcdabc", "abc"))
self.assertEqual([], knuth_morris_pratt("aabcdaab", "aba"))

if __name__ == "__main__":
unittest.main()

0 comments on commit c675beb

Please sign in to comment.