1. Pure Backtracking DFS
Intuition
Iterate end from start to s.length() - 1. If dictSet.count(s.substr(start, end - start + 1)), push to path, recurse on end + 1, and pop.
When to apply: Basic recursive backtracking over all dictionary prefixes.
Algorithm
- Step 1: Store dictionary words in a HashSet for O(1) word lookup.
- Step 2: Define backtrack(start, currentWords).
- Step 3: Base case: if start == s.length, join currentWords with space and add to result.
- Step 4: Loop end from start + 1 to s.length.
- Step 5: If wordSet contains s.substring(start, end), push word, recurse on backtrack(end), and pop.
#include <iostream>#include <vector>#include <string>#include <unordered_set> class Solution {public: void backtrack(const std::string& s, int start, const std::unordered_set<std::string>& dict, std::vector<std::string>& path, std::vector<std::string>& result) { if (start == (int)s.length()) { std::string sentence = path[0]; for (int i = 1; i < (int)path.size(); i++) { sentence += " " + path[i]; } result.push_back(sentence); return; } for (int end = start; end < (int)s.length(); end++) { std::string word = s.substr(start, end - start + 1); if (dict.count(word)) { path.push_back(word); backtrack(s, end + 1, dict, path, result); path.pop_back(); } } } std::vector<std::string> wordBreak(std::string s, std::vector<std::string>& wordDict) { std::unordered_set<std::string> dict(wordDict.begin(), wordDict.end()); std::vector<std::string> result, path; backtrack(s, 0, dict, path, result); return result; }}; int main() { Solution solver; std::string s = "catsanddog"; std::vector<std::string> dict = {"cat", "cats", "and", "sand", "dog"}; std::vector<std::string> res = solver.wordBreak(s, dict); std::cout << "Word Break Sentences for 'catsanddog':\n"; for (const auto& str : res) { std::cout << "\"" << str << "\"\n"; } return 0;}Time & Space Complexity
- Time complexity:
O(2^N * N)— Can branch up to 2^(N-1) ways with O(N) string construction. - Space complexity:
O(N)— O(N) recursion depth and path tokens array.