1. Hash Set of Generated Substrings
Intuition
Iterate all pairs of (i, j) with 0 <= i <= j < n. Extract substring s[i..j] and insert into an unordered set. Return set.size() + 1.
When to apply: Quick sanity checks on small strings (n <= 100).
Algorithm
- Step 1: Initialize an empty unordered set of strings.
- Step 2: Loop i from 0 to n-1. Inner loop j from i to n-1.
- Step 3: Extract substring s.substr(i, j - i + 1) and insert into set.
- Step 4: Return set.size() + 1 (accounting for the empty string).
#include <iostream>#include <string>#include <unordered_set>using namespace std; class Solution {public: int countDistinctSubstrings(string s) { int n = s.length(); unordered_set<string> uniqueSubs; for (int i = 0; i < n; i++) { string current = ""; for (int j = i; j < n; j++) { current += s[j]; uniqueSubs.insert(current); } } return uniqueSubs.size() + 1; // +1 for empty string }}; int main() { Solution sol; string s = "abab"; cout << "Distinct substrings in \"" << s << "\": " << sol.countDistinctSubstrings(s) << endl; return 0;}Time & Space Complexity
- Time complexity:
O(n^3)— O(n2) substrings, each taking O(n) time to copy and compute hash. - Space complexity:
O(n^3)— Set stores up to O(n2) substrings of length up to n.
Why Brute Force Doesn't Scale:
For n = 1000, n*(n+1)/2 ~ 500,000 substrings. Copying strings requires ~250MB and billions of CPU cycles, risking TLE.
Trie allocates pointers on the fly in O(1) without a single string allocation, finishing in under 30ms.