<p>Given a string <code>s</code>, partition <code>s</code> such that every <span data-keyword="substring-nonempty">substring</span> of the partition is a <span data-keyword="palindrome-string"><strong>palindrome</strong></span>. Return <em>all possible palindrome partitioning of </em><code>s</code>.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<pre><strong>Input:</strong> s = "aab"
<strong>Output:</strong> [["a","a","b"],["aa","b"]]
</pre><p><strong class="example">Example 2:</strong></p>
<pre><strong>Input:</strong> s = "a"
<strong>Output:</strong> [["a"]]
</pre>
<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>1 &lt;= s.length &lt;= 16</code></li>
	<li><code>s</code> contains only lowercase English letters.</li>
</ul>

from collections.abc import Generator
from functools import lru_cache

class Solution:
    def partition(self, string: str) -> Generator[list[str], None, None]:
        @lru_cache()
        def is_palindrome(left: int, right: int) -> bool:
            while left < right:
                if string[left] != string[right]:
                    return False
                left, right = left + 1, right - 1
            return True

        def backtrack(path: list[str], left: int) -> Generator[list[str], None, None]:
            if left == end:
                yield path.copy()
                return
            for right in range(left, end):
                if is_palindrome(left, right):
                    path.append(string[left : right + 1])
                    yield from backtrack(path, right + 1)
                    del path[-1]

        end = len(string)
        return backtrack([], 0)
22901