Finding all the common substrings of given two strings
ML System Design practice on Codemia
Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.
Introduction
In computer science, a substring of a string is a contiguous sequence of characters within that string. Finding common substrings between two given strings is a fundamental problem that is used in various applications, including bioinformatics, text comparison, and plagiarism detection. This article explores different approaches to finding all the common substrings of two given strings, explains the algorithms involved, and provides examples.
Problem Definition
Given two strings `S1` and `S2`, the task is to find all common substrings of these strings. A common substring is a contiguous sequence of characters that appears in both strings.
Approaches for Finding Common Substrings
Finding common substrings can be tackled using different approaches, each with its complexity and efficiency:
1. Brute Force Approach
The brute force approach involves generating all possible substrings of both strings and comparing them. Here's a detailed look at how this can be implemented:
- Step 1: Generate all possible substrings of `S1`.
- Step 2: For each substring in `S1`, check if it appears in `S2`.
- Step 3: Collect all substrings that are present in both `S1` and `S2`.
Time Complexity: The time complexity of this method is , where `n` is the length of `S1`, and `m` is the length of `S2`. This makes the brute force approach inefficient for longer strings.
Example: Consider `S1 = "ababc"` and `S2 = "abcba"`. The common substrings would be "a", "ab", "b", and "abc".
2. Suffix Trees
A more efficient method involves using a data structure known as the suffix tree:
- Construction: Construct a suffix tree for one of the strings, say `S1`. A suffix tree is a compressed trie containing all the suffixes of `S1`.
- Traverse: Traverse the suffix tree using substrings of `S2` to find common substrings.
- Collect: Collect nodes in the tree that correspond to the suffixes appearing in both strings.
Time Complexity: Constructing the suffix tree takes time, and searching each substring can be done in time, making this method more efficient with a total complexity of .
Example: For `S1 = "banana"` and `S2 = "panama"`, the suffix tree created for "banana" can be used to efficiently find common substrings like "ana", "a", and "an".
3. Dynamic Programming
The dynamic programming approach is commonly used to find the longest common substring and can be adapted to find all common substrings:
- Table: Create a 2D table `dp` where `dp[i][j]` stores the length of the longest common suffix of substrings `S1[0..i-1]` and `S2[0..j-1]`.
- Filling the Table: If `S1[i-1] == S2[j-1]`, then `dp[i][j] = dp[i-1][j-1] + 1`. Otherwise, `dp[i][j] = 0`.
- Extract Substrings: For each cell `dp[i][j] > 0`, extract the current longest common substring from `S1`.
Time Complexity: This method has a time complexity of , which is efficient compared to brute force for medium-sized strings.
Example: Using `S1 = "zzabcde"` and `S2 = "xyabcz"`, the `dp` table helps identify common substrings like "abc".
4. Rolling `Hash` and Binary Search
This method uses hashing combined with binary search to optimize the search for common substrings:
- Binary Search: Use binary search to find the maximum length of common substrings.
- Hashing: Compute hashes for substrings of length in both strings and check for matches.
Time Complexity: With proper hash functions and collision handling, this approach can achieve time complexity.
Example: For strings like `S1 = "abc"` and `S2 = "cab"`, the approach can efficiently determine that the common substrings are "a", "b", and "c".
Summary
The table below summarizes different methods and their complexities:
| Method | Description | Time Complexity |
| Brute Force | Compare all substrings | |
| Suffix Trees | Use compressed trie structure | |
| Dynamic Programming | 2D table of longest suffixes | |
Rolling Hash + Binary Search | Efficient hash comparison |
Additional Considerations
- Space Complexity: Suffix trees and dynamic programming carry different space complexities, so the choice of method may depend on available memory resources.
- Application: Choosing the right method may depend on the context. For example, dynamic programming is preferred for problems like the longest common substring, while suffix trees may be advantageous when working with very large datasets.
- Implementation: Efficient implementations often involve complex algorithmic insights (like Ukkonen's algorithm for suffix trees) but are worthwhile due to performance benefits.
In conclusion, finding all common substrings of two given strings can be accomplished using various methods, each suited to different scenarios based on efficiency requirements and resource constraints. Understanding these methods enables better decision-making when tackling problems involving substring analysis.
Related reading
- Finding head of a noun phrase in NLTK and stanford parse according to the rules of finding head of a NP
- Finding how similar two strings are
- Finding meaningful sub-sentences from a sentence
- Focused Named Entity Recognition NER?
- Finding all the shortest paths between two nodes in unweighted undirected graph
- Finding all the unique permutations of a string without generating duplicates
- Finding all the subsets of a set
- Finding an axis-aligned rectangle inside a polygon

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
ML System Design practice on Codemia
Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.