From 57a3bfbfc165024d400ab9c7c49d4223c30cc757 Mon Sep 17 00:00:00 2001 From: nikalosa Date: Fri, 12 Jun 2020 14:49:00 +0400 Subject: [PATCH 1/5] Implement prefix function, knuth-morris-pratt another usage --- strings/prefix_function.py | 67 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 strings/prefix_function.py diff --git a/strings/prefix_function.py b/strings/prefix_function.py new file mode 100644 index 000000000000..8b6a29854789 --- /dev/null +++ b/strings/prefix_function.py @@ -0,0 +1,67 @@ +""" +https://cp-algorithms.com/string/prefix-function.html + +Prefix function Knuth–Morris–Pratt algorithm + +Different algorithm than Knuth-Morris-Pratt pattern finding + +E.x. Finding longest prefix which is also suffix + +Time Complexity: O(n) - where n is the length of the string + +""" + + +def prefix_function(input_string: str) -> list: + """ + For the given string this function computes value for each index(i), + which represents the longest coincidence of prefix and sufix + for given substring (input_str[0...i]) + + For the value of the first element the algorithm always returns 0 + + >>> prefix_function("aabcdaabc") + [0, 1, 0, 0, 0, 1, 2, 3, 4] + >>> prefix_function("asdasdad") + [0, 0, 0, 1, 2, 3, 4, 0] + + """ + + # list for the result values + prefix_result = [0] * len(input_string) + + for i in range(1, len(input_string)): + + # use last results for better performance - dynamic programming + j = prefix_result[i - 1] + while j > 0 and input_string[i] != input_string[j]: + j = prefix_result[j - 1] + + if input_string[i] == input_string[j]: + j += 1 + prefix_result[i] = j + + return prefix_result + + +def longest_prefix(input_str: str) -> int: + """ + Prefix-function use case + Finding longest prefix which is sufix as well + + >>> longest_prefix("aabcdaabc") + 4 + >>> longest_prefix("asdasdad") + 4 + >>> longest_prefix("abcab") + 2 + """ + + prefix_result = prefix_function(input_str) + # just returning maximum value of the array gives us answer + return max(prefix_result) + + +if __name__ == "__main__": + import doctest + doctest.testmod() From 135c4588a3ca74250d9716aa548e8c497d6c034c Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Fri, 12 Jun 2020 10:50:15 +0000 Subject: [PATCH 2/5] fixup! Format Python code with psf/black push --- strings/prefix_function.py | 1 + 1 file changed, 1 insertion(+) diff --git a/strings/prefix_function.py b/strings/prefix_function.py index 8b6a29854789..f90a1c1b14c7 100644 --- a/strings/prefix_function.py +++ b/strings/prefix_function.py @@ -64,4 +64,5 @@ def longest_prefix(input_str: str) -> int: if __name__ == "__main__": import doctest + doctest.testmod() From 33a04c281970a6c1ae2d3124bdaf172d4200b87a Mon Sep 17 00:00:00 2001 From: Nika Losaberidze Date: Mon, 15 Jun 2020 12:54:41 +0400 Subject: [PATCH 3/5] Fix style --- strings/prefix_function.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/strings/prefix_function.py b/strings/prefix_function.py index f90a1c1b14c7..a51eff0d5182 100644 --- a/strings/prefix_function.py +++ b/strings/prefix_function.py @@ -57,9 +57,8 @@ def longest_prefix(input_str: str) -> int: 2 """ - prefix_result = prefix_function(input_str) # just returning maximum value of the array gives us answer - return max(prefix_result) + return max(prefix_function(input_str)) if __name__ == "__main__": From 84d9f3cd4d7e8e18f8eb8926262cc96b49c49cb8 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Mon, 15 Jun 2020 08:55:28 +0000 Subject: [PATCH 4/5] updating DIRECTORY.md --- DIRECTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index c90043aa734f..bf4c19bb5a21 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -641,6 +641,7 @@ * [Manacher](https://github.com/TheAlgorithms/Python/blob/master/strings/manacher.py) * [Min Cost String Conversion](https://github.com/TheAlgorithms/Python/blob/master/strings/min_cost_string_conversion.py) * [Naive String Search](https://github.com/TheAlgorithms/Python/blob/master/strings/naive_string_search.py) + * [Prefix Function](https://github.com/TheAlgorithms/Python/blob/master/strings/prefix_function.py) * [Rabin Karp](https://github.com/TheAlgorithms/Python/blob/master/strings/rabin_karp.py) * [Remove Duplicate](https://github.com/TheAlgorithms/Python/blob/master/strings/remove_duplicate.py) * [Reverse Words](https://github.com/TheAlgorithms/Python/blob/master/strings/reverse_words.py) From c3c4957d8c39c036dd9dd87f5719d3af86c0a952 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 17 Jun 2020 18:19:23 +0200 Subject: [PATCH 5/5] Update prefix_function.py --- strings/prefix_function.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/strings/prefix_function.py b/strings/prefix_function.py index a51eff0d5182..9e6dbbf5408f 100644 --- a/strings/prefix_function.py +++ b/strings/prefix_function.py @@ -8,7 +8,6 @@ E.x. Finding longest prefix which is also suffix Time Complexity: O(n) - where n is the length of the string - """ @@ -24,7 +23,6 @@ def prefix_function(input_string: str) -> list: [0, 1, 0, 0, 0, 1, 2, 3, 4] >>> prefix_function("asdasdad") [0, 0, 0, 1, 2, 3, 4, 0] - """ # list for the result values