Skip to content

Commit f1e2e3a

Browse files
advikkabracertik
authored andcommitted
Improved str.count() algorithm using Knuth-Morris-Pratt
1 parent 496f29e commit f1e2e3a

File tree

1 file changed

+42
-9
lines changed

1 file changed

+42
-9
lines changed

src/runtime/lpython_builtin.py

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -637,17 +637,50 @@ def _lpython_str_capitalize(x: str) -> str:
637637

638638

639639
@overload
640-
def _lpython_str_count(x: str, y: str) -> i32:
641-
if(len(y) == 0): return len(x) + 1
640+
def _lpython_str_count(s: str, sub: str) -> i32:
641+
s_len :i32; sub_len :i32; flag: bool; _len: i32;
642+
count: i32; i: i32;
643+
lps: list[i32] = []
644+
s_len = len(s)
645+
sub_len = len(sub)
642646

643-
count: i32 = 0
644-
curr_char: str
645-
i: i32
647+
if sub_len == 0:
648+
return s_len + 1
649+
650+
count = 0
651+
652+
for i in range(sub_len):
653+
lps.append(0)
654+
655+
i = 1
656+
_len = 0
657+
while i < sub_len:
658+
if sub[i] == sub[_len]:
659+
_len += 1
660+
lps[i] = _len
661+
i += 1
662+
else:
663+
if _len != 0:
664+
_len = lps[_len - 1]
665+
else:
666+
lps[i] = 0
667+
i += 1
646668

647-
for i in range(len(x)):
648-
curr_char = x[i]
649-
if curr_char == y[0]:
650-
count += i32(x[i:i+len(y)] == y)
669+
j: i32
670+
j = 0
671+
i = 0
672+
while (s_len - i) >= (sub_len - j):
673+
if sub[j] == s[i]:
674+
i += 1
675+
j += 1
676+
if j == sub_len:
677+
count += 1
678+
j = lps[j - 1]
679+
elif i < s_len and sub[j] != s[i]:
680+
if j != 0:
681+
j = lps[j - 1]
682+
else:
683+
i = i + 1
651684

652685
return count
653686

0 commit comments

Comments
 (0)