Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented Suffix Tree Data Structure #11554

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
0d6985c
Implemented KD-Tree Data Structure
Ramy-Badr-Ahmed Aug 28, 2024
6665d23
Implemented KD-Tree Data Structure. updated DIRECTORY.md.
Ramy-Badr-Ahmed Aug 28, 2024
6b3d47e
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 28, 2024
4203cda
Create __init__.py
Ramy-Badr-Ahmed Aug 28, 2024
3222bd3
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 28, 2024
a41ae5b
Replaced legacy `np.random.rand` call with `np.random.Generator` in k…
Ramy-Badr-Ahmed Aug 28, 2024
1668d73
Replaced legacy `np.random.rand` call with `np.random.Generator` in k…
Ramy-Badr-Ahmed Aug 28, 2024
81d6917
added typehints and docstrings
Ramy-Badr-Ahmed Aug 28, 2024
6cddcbd
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 28, 2024
8b238d1
docstring for search()
Ramy-Badr-Ahmed Aug 28, 2024
cd1dd9f
Merge remote-tracking branch 'origin/feature/kd-tree-implementation' …
Ramy-Badr-Ahmed Aug 28, 2024
ead2838
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 28, 2024
543584c
Added tests. Updated docstrings/typehints
Ramy-Badr-Ahmed Aug 28, 2024
ad31f83
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 28, 2024
1322921
updated tests and used | for type annotations
Ramy-Badr-Ahmed Aug 28, 2024
4608a9f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 28, 2024
7c1aa7e
E501 for build_kdtree.py, hypercube_points.py, nearest_neighbour_sear…
Ramy-Badr-Ahmed Aug 29, 2024
ba24e75
I001 for example_usage.py and test_kdtree.py
Ramy-Badr-Ahmed Aug 29, 2024
05975a3
I001 for example_usage.py and test_kdtree.py
Ramy-Badr-Ahmed Aug 29, 2024
31782d1
Update data_structures/kd_tree/build_kdtree.py
Ramy-Badr-Ahmed Sep 3, 2024
6a9b3e1
Update data_structures/kd_tree/example/hypercube_points.py
Ramy-Badr-Ahmed Sep 3, 2024
2fd24d4
Update data_structures/kd_tree/example/hypercube_points.py
Ramy-Badr-Ahmed Sep 3, 2024
2cf9d92
Added new test cases requested in Review. Refactored the test_build_k…
Ramy-Badr-Ahmed Sep 3, 2024
a3803ee
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 3, 2024
f1f5862
Considered ruff errors
Ramy-Badr-Ahmed Sep 3, 2024
ec6559d
Merge remote-tracking branch 'origin/feature/kd-tree-implementation' …
Ramy-Badr-Ahmed Sep 3, 2024
5c07a1a
Considered ruff errors
Ramy-Badr-Ahmed Sep 3, 2024
3c09ac1
Apply suggestions from code review
cclauss Sep 3, 2024
bab43e7
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 3, 2024
a10ff15
Update kd_node.py
cclauss Sep 3, 2024
d77a285
imported annotations from __future__
Ramy-Badr-Ahmed Sep 3, 2024
0426806
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 3, 2024
9c4cbd4
Implementation of the suffix tree data structure
Ramy-Badr-Ahmed Sep 7, 2024
95ae328
Adding data to DIRECTORY.md
Ramy-Badr-Ahmed Sep 7, 2024
1454bb2
Minor file renaming
Ramy-Badr-Ahmed Sep 7, 2024
c559de9
Merge branch 'TheAlgorithms:master' into master
Ramy-Badr-Ahmed Sep 7, 2024
a2b3a86
minor correction
Ramy-Badr-Ahmed Sep 7, 2024
323d53a
Merge branch 'feature/suffix-tree-implementation'
Ramy-Badr-Ahmed Sep 7, 2024
4fd5c3e
Merge branch 'TheAlgorithms:master' into feature/kd-tree-implementation
Ramy-Badr-Ahmed Sep 7, 2024
51832af
renaming in DIRECTORY.md
Ramy-Badr-Ahmed Sep 7, 2024
5097923
Merge branch 'feature/suffix-tree-implementation'
Ramy-Badr-Ahmed Sep 7, 2024
283a9b7
Merge branch 'feature/kd-tree-implementation'
Ramy-Badr-Ahmed Sep 7, 2024
41996b9
Merge branch 'master' into feature/suffix-tree-implementation
Ramy-Badr-Ahmed Sep 7, 2024
6b5bddc
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 7, 2024
79f40ea
Considering ruff part-1
Ramy-Badr-Ahmed Sep 7, 2024
bac6962
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 7, 2024
87909da
Considering ruff part-2
Ramy-Badr-Ahmed Sep 7, 2024
ce8e35d
Merge remote-tracking branch 'origin/feature/suffix-tree-implementati…
Ramy-Badr-Ahmed Sep 7, 2024
288a4f0
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 7, 2024
93e910d
Considering ruff part-3
Ramy-Badr-Ahmed Sep 7, 2024
e375de7
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 7, 2024
52ba6d2
Considering ruff part-4
Ramy-Badr-Ahmed Sep 7, 2024
531252e
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 7, 2024
7479d2d
Considering ruff part-5
Ramy-Badr-Ahmed Sep 7, 2024
819f3d1
Merge branch 'feature/suffix-tree-implementation'
Ramy-Badr-Ahmed Sep 7, 2024
d8eb924
Implemented Suffix Tree Data Structure.
Ramy-Badr-Ahmed Sep 28, 2024
c70b3ce
Merge branch 'feature/suffix-tree-implementation'
Ramy-Badr-Ahmed Sep 28, 2024
666bb6f
updating DIRECTORY.md
Ramy-Badr-Ahmed Sep 28, 2024
3a6c8a3
Implemented Suffix Tree Data Structure.
Ramy-Badr-Ahmed Sep 28, 2024
cd8be17
Merge branch 'feature/suffix-tree-implementation'
Ramy-Badr-Ahmed Sep 28, 2024
3de5ff3
Merge branch 'TheAlgorithms:master' into master
Ramy-Badr-Ahmed Sep 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,13 @@
* [Stack With Doubly Linked List](data_structures/stacks/stack_with_doubly_linked_list.py)
* [Stack With Singly Linked List](data_structures/stacks/stack_with_singly_linked_list.py)
* [Stock Span Problem](data_structures/stacks/stock_span_problem.py)
* Suffix Tree
* Example
* [Example Usage](data_structures/suffix_tree/example/example_usage.py)
* [Suffix Tree](data_structures/suffix_tree/suffix_tree.py)
* [Suffix Tree Node](data_structures/suffix_tree/suffix_tree_node.py)
* Tests
* [Test Suffix Tree](data_structures/suffix_tree/tests/test_suffix_tree.py)
* Trie
* [Radix Tree](data_structures/trie/radix_tree.py)
* [Trie](data_structures/trie/trie.py)
Expand Down
8 changes: 8 additions & 0 deletions data_structures/kd_tree/build_kdtree.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed)
# in Pull Request: #11532
# https://github.com/TheAlgorithms/Python/pull/11532
#
# Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request
# addressing bugs/corrections to this file.
# Thank you!

from data_structures.kd_tree.kd_node import KDNode


Expand Down
8 changes: 8 additions & 0 deletions data_structures/kd_tree/example/example_usage.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed)
# in Pull Request: #11532
# https://github.com/TheAlgorithms/Python/pull/11532
#
# Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request
# addressing bugs/corrections to this file.
# Thank you!

import numpy as np

from data_structures.kd_tree.build_kdtree import build_kdtree
Expand Down
8 changes: 8 additions & 0 deletions data_structures/kd_tree/example/hypercube_points.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed)
# in Pull Request: #11532
# https://github.com/TheAlgorithms/Python/pull/11532
#
# Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request
# addressing bugs/corrections to this file.
# Thank you!

import numpy as np


Expand Down
8 changes: 8 additions & 0 deletions data_structures/kd_tree/kd_node.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed)
# in Pull Request: #11532
# https://github.com/TheAlgorithms/Python/pull/11532
#
# Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request
# addressing bugs/corrections to this file.
# Thank you!

from __future__ import annotations


Expand Down
8 changes: 8 additions & 0 deletions data_structures/kd_tree/nearest_neighbour_search.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed)
# in Pull Request: #11532
# https://github.com/TheAlgorithms/Python/pull/11532
#
# Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request
# addressing bugs/corrections to this file.
# Thank you!

from data_structures.kd_tree.kd_node import KDNode


Expand Down
8 changes: 8 additions & 0 deletions data_structures/kd_tree/tests/test_kdtree.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed)
# in Pull Request: #11532
# https://github.com/TheAlgorithms/Python/pull/11532
#
# Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request
# addressing bugs/corrections to this file.
# Thank you!

import numpy as np
import pytest

Expand Down
Empty file.
Empty file.
37 changes: 37 additions & 0 deletions data_structures/suffix_tree/example/example_usage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed)
# in Pull Request: #11554
# https://github.com/TheAlgorithms/Python/pull/11554
#
# Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request
# addressing bugs/corrections to this file.
# Thank you!

from data_structures.suffix_tree.suffix_tree import SuffixTree


def main() -> None:
"""
Demonstrate the usage of the SuffixTree class.

- Initializes a SuffixTree with a predefined text.
- Defines a list of patterns to search for within the suffix tree.
- Searches for each pattern in the suffix tree.

Patterns tested:
- "ana" (found) --> True
- "ban" (found) --> True
- "na" (found) --> True
- "xyz" (not found) --> False
- "mon" (found) --> True
"""
text = "monkey banana"
suffix_tree = SuffixTree(text)

patterns = ["ana", "ban", "na", "xyz", "mon"]
for pattern in patterns:
found = suffix_tree.search(pattern)
print(f"Pattern '{pattern}' found: {found}")


if __name__ == "__main__":
main()
66 changes: 66 additions & 0 deletions data_structures/suffix_tree/suffix_tree.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed)
# in Pull Request: #11554
# https://github.com/TheAlgorithms/Python/pull/11554
#
# Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request
# addressing bugs/corrections to this file.
# Thank you!

from data_structures.suffix_tree.suffix_tree_node import SuffixTreeNode


class SuffixTree:
def __init__(self, text: str) -> None:
"""
Initializes the suffix tree with the given text.

Args:
text (str): The text for which the suffix tree is to be built.
"""
self.text: str = text
self.root: SuffixTreeNode = SuffixTreeNode()
self.build_suffix_tree()

def build_suffix_tree(self) -> None:
"""
Builds the suffix tree for the given text by adding all suffixes.
"""
text = self.text
n = len(text)
for i in range(n):
suffix = text[i:]
self._add_suffix(suffix, i)

def _add_suffix(self, suffix: str, index: int) -> None:
"""
Adds a suffix to the suffix tree.

Args:
suffix (str): The suffix to add.
index (int): The starting index of the suffix in the original text.
"""
node = self.root
for char in suffix:
if char not in node.children:
node.children[char] = SuffixTreeNode()
node = node.children[char]
node.is_end_of_string = True
node.start = index
node.end = index + len(suffix) - 1

def search(self, pattern: str) -> bool:
"""
Searches for a pattern in the suffix tree.

Args:
pattern (str): The pattern to search for.

Returns:
bool: True if the pattern is found, False otherwise.
"""
node = self.root
for char in pattern:
if char not in node.children:
return False
node = node.children[char]
return True
36 changes: 36 additions & 0 deletions data_structures/suffix_tree/suffix_tree_node.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed)
# in Pull Request: #11554
# https://github.com/TheAlgorithms/Python/pull/11554
#
# Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request
# addressing bugs/corrections to this file.
# Thank you!

from __future__ import annotations


class SuffixTreeNode:
def __init__(
self,
children: dict[str, SuffixTreeNode] | None = None,
is_end_of_string: bool = False,
start: int | None = None,
end: int | None = None,
suffix_link: SuffixTreeNode | None = None,
) -> None:
"""
Initializes a suffix tree node.

Parameters:
children (dict[str, SuffixTreeNode] | None): The children of this node.
is_end_of_string (bool): Indicates if this node represents
the end of a string.
start (int | None): The start index of the suffix in the text.
end (int | None): The end index of the suffix in the text.
suffix_link (SuffixTreeNode | None): Link to another suffix tree node.
"""
self.children = children or {}
self.is_end_of_string = is_end_of_string
self.start = start
self.end = end
self.suffix_link = suffix_link
Empty file.
59 changes: 59 additions & 0 deletions data_structures/suffix_tree/tests/test_suffix_tree.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed)
# in Pull Request: #11554
# https://github.com/TheAlgorithms/Python/pull/11554
#
# Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request
# addressing bugs/corrections to this file.
# Thank you!

import unittest

from data_structures.suffix_tree.suffix_tree import SuffixTree


class TestSuffixTree(unittest.TestCase):
def setUp(self) -> None:
"""Set up the initial conditions for each test."""
self.text = "banana"
self.suffix_tree = SuffixTree(self.text)

def test_search_existing_patterns(self) -> None:
"""Test searching for patterns that exist in the suffix tree."""
patterns = ["ana", "ban", "na"]
for pattern in patterns:
with self.subTest(pattern=pattern):
assert self.suffix_tree.search(
pattern
), f"Pattern '{pattern}' should be found."

def test_search_non_existing_patterns(self) -> None:
"""Test searching for patterns that do not exist in the suffix tree."""
patterns = ["xyz", "apple", "cat"]
for pattern in patterns:
with self.subTest(pattern=pattern):
assert not self.suffix_tree.search(
pattern
), f"Pattern '{pattern}' should not be found."

def test_search_empty_pattern(self) -> None:
"""Test searching for an empty pattern."""
assert self.suffix_tree.search(""), "An empty pattern should be found."

def test_search_full_text(self) -> None:
"""Test searching for the full text."""
assert self.suffix_tree.search(
self.text
), "The full text should be found in the suffix tree."

def test_search_substrings(self) -> None:
"""Test searching for substrings of the full text."""
substrings = ["ban", "ana", "a", "na"]
for substring in substrings:
with self.subTest(substring=substring):
assert self.suffix_tree.search(
substring
), f"Substring '{substring}' should be found."


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