1+ """Palindrome partitioning module.
2+
3+ Given a string s, partition s such that every substring of the partition is a palindrome.
4+ Find the minimum cuts needed for a palindrome partitioning of s.
5+
6+ Time complexity: O(n^2)
7+ Space complexity: O(n^2) [can be optimized to O(n)]
8+ """
9+
10+ from typing import List , Tuple , Union
11+
12+
13+ def find_minimum_partitions (
14+ s : str , return_partitions : bool = False
15+ ) -> Union [int , Tuple [int , List [str ]]]:
16+ """Return minimum cuts and optionally one valid partitioning."""
17+ n = len (s )
18+ if n <= 1 or s == s [::- 1 ]:
19+ return (0 , [s ]) if return_partitions else 0
20+
21+ # DP tables
22+ cuts = [0 ] * n
23+ is_palindrome = [[False ] * n for _ in range (n )]
24+ parent = [- 1 ] * n # tracks where to jump back for reconstruction
25+
26+ for i in range (n ):
27+ min_cuts = i
28+ for j in range (i + 1 ):
29+ if s [j ] == s [i ] and (i - j <= 1 or is_palindrome [j + 1 ][i - 1 ]):
30+ is_palindrome [j ][i ] = True
31+ if j == 0 :
32+ min_cuts = 0
33+ parent [i ] = - 1
34+ else :
35+ candidate = cuts [j - 1 ] + 1
36+ if candidate < min_cuts :
37+ min_cuts = candidate
38+ parent [i ] = j - 1
39+ cuts [i ] = min_cuts
40+
41+ if not return_partitions :
42+ return cuts [- 1 ]
43+
44+ # Reconstruct one valid partitioning
45+ partitions : List [str ] = []
46+ i = n - 1
47+ while i >= 0 :
48+ start = parent [i ] + 1 if parent [i ] != - 1 else 0
49+ partitions .append (s [start :i + 1 ])
50+ if parent [i ] == - 1 :
51+ break
52+ i = parent [i ]
53+
54+ partitions .reverse ()
55+ return (cuts [- 1 ], partitions )
56+
57+
58+ if __name__ == "__main__" :
59+ s = input ("enter the string:" ).strip ()
60+ cuts , partitions = find_minimum_partitions (s , return_partitions = True )
61+ print (f"Minimum cuts required: { cuts } " )
62+ print ("One possible palindrome partitioning:" )
63+ print (" | " .join (partitions ))
0 commit comments