[Backtracking] [leetcode] Split string to maximize the number of unique substrings

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); // 回溯,从集合中删除
            }
        }
    }
};

 

Guess you like

Origin blog.csdn.net/hbuxiaoshe/article/details/115144677