topic:
Give you a string s, please split the string and return the maximum number of unique substrings after splitting.
After the string s is split, several non-empty substrings can be obtained, and these substrings should be able to be restored to the original string after concatenation. But each substring that is split must be unique.
Note: A substring is a continuous sequence of characters in a string.
Example 1:
Input: s = "ababccc"
Output: 5
Explanation: One of the largest split methods is ['a','b','ab','c','cc']. Splitting like ['a','b','a','b','c','cc'] does not meet the requirements of the title, because both'a' and'b' appear more than once.
Example 2:
Input: s = "aba"
Output: 2
Explanation: A maximum split method is ['a','ba'].
Example 3:
Input: s = "aa"
Output: 1
Explanation: The string cannot be split further.
prompt:
- 1 <= s.length <= 16
- s contains only lowercase English letters
source:
1593. Split string to maximize the number of unique substrings
Problem-solving ideas: backtracking
Define a set u, used to query whether the new substring exists, if it does not exist, continue.
- Recursive termination condition: string s traversal is complete
- The result meets the condition: compare the current number of substrings to find the largest
- Pruning condition: the number of remaining characters + the current set size + 1 <result, +1 corresponds to the current substring. Even if the current substring does not repeat, even if each of the following characters is a non-repeated substring, the total number of them is less than the number of a previous substring, so there is no need to recurse. 460ms before pruning and 24ms after pruning, the effect is obvious.
class Solution {
public:
int result;
int maxUniqueSplit(string s) {
result = 0;
set<string> u;
back(s, 0, u);
return result;
}
void back(const string& s, int start, set<string>& u) {
if (start == s.size()) {
if (result < u.size()) result = u.size();
return;
}
for (int i = start; i < s.size(); i++) {
if (s.size() - i - 1 + u.size() + 1 < result) break; // 剪枝
string sub(s, start, i-start+1);
if (u.find(sub) == u.end()) {
u.insert(sub); // 加入集合
back(s, i+1, u); // 递归
u.erase(sub); // 回溯,从集合中删除
}
}
}
};