package main

import (
	"slices"
)

func getPalindromes(s string) [][]bool {
	size := len(s) + 1

	// Create a DP table
	palindromes := make([][]bool, size)
	for i := range size {
		palindromes[i] = make([]bool, size)
	}

	// Set the ranges that represent a palindrome
	checkPalindromes := func(i, j int) {
		if i < 0 || j >= len(s) {
			return
		}

		for i >= 0 && j < len(s) && s[i] == s[j] {
			palindromes[i][j+1] = true

			i -= 1
			j += 1
		}
	}
	for i, _ := range s {
		checkPalindromes(i, i)
		checkPalindromes(i, i+1)
	}

	return palindromes
}

func getPartitions(s string, palindromes [][]bool) [][]string {
	var partitions [][]string
	var currentPartition []string

	var dfs func(int)
	dfs = func(i int) {
		if i >= len(s) && len(currentPartition) > 0 {
			partitions = append(partitions, slices.Clone(currentPartition))
			return
		} else if i >= len(s) {
			return
		}

		for j := len(s); j > i; j-- {
			if !palindromes[i][j] {
				continue
			}

			currentPartition = append(currentPartition, s[i:j])
			dfs(j)
			currentPartition = currentPartition[:len(currentPartition)-1]
		}
	}

	dfs(0)
	return partitions
}

func partition(s string) [][]string {
	return getPartitions(s, getPalindromes(s))
}