Intuition
Precompute which substrings are palindromes, then let dp[i] be the fewest cuts for the prefix ending at i: 0 if the whole prefix is a palindrome, else 1 + the best earlier cut before a palindromic tail.
Explanation
Two DPs
- Palindrome table
pal[i][j]= iss[i..j]a palindrome? Fill by increasing length usingpal[i][j] = (s[i]==s[j]) and pal[i+1][j-1]. - Min-cut
dp[i]= minimum cuts fors[:i+1]. Ifs[0..i]is itself a palindrome,dp[i] = 0. Otherwisedp[i] = min over j of dp[j-1] + 1wheres[j..i]is a palindrome.
dp[i] = 0 if pal[0][i] else min(dp[j-1]+1 for j in 1..i if pal[j][i])
Worked example
"aab" → cut once into "aa" | "b" → 1.
Complexity
- Time: O(n²).
- Space: O(n²).
Implementation
class Solution {
public int minCut(String s) {
int n = s.length();
if (n <= 1) return 0;
boolean[][] pal = new boolean[n][n];
for (int i = 0; i < n; i++) pal[i][i] = true;
for (int len = 2; len <= n; len++) {
for (int i = 0; i + len - 1 < n; i++) {
int j = i + len - 1;
if (s.charAt(i) == s.charAt(j) && (len == 2 || pal[i + 1][j - 1])) {
pal[i][j] = true;
}
}
}
int[] dp = new int[n];
for (int i = 0; i < n; i++) {
if (pal[0][i]) {
dp[i] = 0;
} else {
int best = Integer.MAX_VALUE;
for (int j = 1; j <= i; j++) {
if (pal[j][i]) best = Math.min(best, dp[j - 1] + 1);
}
dp[i] = best;
}
}
return dp[n - 1];
}
}