// Source: https://leetcode.com/problems/split-a-string-into-the-max-number-of-unique-substrings // Split a String Into the Max Number of Unique Substrings // Difficulty: Medium // Author: Mu Yang <http://muyang.pro> //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Given a string s, return the maximum number of unique substrings that the given string can be split into. // You can split string s into any list of non-empty substrings, where the concatenation of the substrings forms the original string. However, you must split the substrings such that all of them are unique. // A substring is a contiguous sequence of characters within a string. // // Example 1: // // Input: s = "ababccc" // Output: 5 // Explanation: One way to split maximally is ['a', 'b', 'ab', 'c', 'cc']. Splitting like ['a', 'b', 'a', 'b', 'c', 'cc'] is not valid as you have 'a' and 'b' multiple times. // // Example 2: // // Input: s = "aba" // Output: 2 // Explanation: One way to split maximally is ['a', 'ba']. // // Example 3: // // Input: s = "aa" // Output: 1 // Explanation: It is impossible to split the string any further. // // Constraints: // // 1 <= s.length <= 16 // s contains only lower case English letters. // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// package main // Loop for all possible splits func maxUniqueSplit(s string) int { n := len(s) - 1 m := uint(1) << n res := 0 OUTER: for bits := uint(0); bits < m; bits++ { words := make(map[string]bool, n+1) // Construct split substr := "" for b := 0; b < n; b++ { // loop for bits substr += string(s[b]) if (bits >> b & 1) == 1 { if words[substr] { continue OUTER } words[substr] = true substr = "" } } substr += string(s[n]) if words[substr] { continue OUTER } words[substr] = true res = max(res, len(words)) } return res } // Backtracking func maxUniqueSplit2(s string) int { n := len(s) seen := make(map[string]bool, 1<<n) var backtrack func(start int) int backtrack = func(start int) int { if start == n { return 0 } maxSplits := 0 for end := start + 1; end <= n; end++ { word := s[start:end] if seen[word] { continue } seen[word] = true maxSplits = max(maxSplits, 1+backtrack(end)) seen[word] = false } return maxSplits } return backtrack(0) }