<p>Given a string&nbsp;<code>s</code><var>,</var>&nbsp;return <em>the maximum&nbsp;number of unique substrings that the given string can be split into</em>.</p>

<p>You can split string&nbsp;<code>s</code> into any list of&nbsp;<strong>non-empty substrings</strong>, where the concatenation of the substrings forms the original string.&nbsp;However, you must split the substrings such that all of them are <strong>unique</strong>.</p>

<p>A <strong>substring</strong> is a contiguous sequence of characters within a string.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>

<pre>
<strong>Input:</strong> s = &quot;ababccc&quot;
<strong>Output:</strong> 5
<strong>Explanation</strong>: One way to split maximally is [&#39;a&#39;, &#39;b&#39;, &#39;ab&#39;, &#39;c&#39;, &#39;cc&#39;]. Splitting like [&#39;a&#39;, &#39;b&#39;, &#39;a&#39;, &#39;b&#39;, &#39;c&#39;, &#39;cc&#39;] is not valid as you have &#39;a&#39; and &#39;b&#39; multiple times.
</pre>

<p><strong class="example">Example 2:</strong></p>

<pre>
<strong>Input:</strong> s = &quot;aba&quot;
<strong>Output:</strong> 2
<strong>Explanation</strong>: One way to split maximally is [&#39;a&#39;, &#39;ba&#39;].
</pre>

<p><strong class="example">Example 3:</strong></p>

<pre>
<strong>Input:</strong> s = &quot;aa&quot;
<strong>Output:</strong> 1
<strong>Explanation</strong>: It is impossible to split the string any further.
</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li>
	<p><code>1 &lt;= s.length&nbsp;&lt;= 16</code></p>
	</li>
	<li>
	<p><code>s</code> contains&nbsp;only lower case English letters.</p>
	</li>
</ul>

class Node:
    def __init__(self, val):
        self.val = val
        self.hmap = {}
        self.terminate = False
class Trie:
    def __init__(self):
        self.head = Node("0")
        self.size = 0
    
    def search(self, word):
        it = self.head
        for i in word:
            if i not in it.hmap:    return False
            it = it.hmap[i]
        if it.terminate:    return True
        return False
    
    def addWord(self, word):
        it = self.head
        for i in word:
            if i not in it.hmap:    it.hmap[i] = Node(i)
            it = it.hmap[i]
        it.terminate, self.size = True, self.size + 1
        
    def removeWord(self, word):
        it = self.head
        for i in word:
            it = it.hmap[i]
        it.terminate, self.size = False, self.size -1
        
class Solution:
    def maxUniqueSplit(self, s: str) -> int:
        ans, obj = 0, Trie()
        def backTrack(s, idx, n):
            nonlocal ans
            if idx == n:
                ans = max(ans, obj.size)
                return
            for i in range(idx, n):
                if not obj.search(s[idx: i+1]):
                    obj.addWord(s[idx: i+1])
                    backTrack(s, i+1, n)
                    obj.removeWord(s[idx: i+1])
        backTrack(s, 0, len(s))
        return ans
16900