Editorial
Let be the input string. The substring is a palindrome if one of the following conditions is satisfied:
(the substring is empty or consists of a single character);
and the substring is a palindrome;
Let the function return if is a palindrome, and otherwise. The values of are stored in the cells .
Let the function return the minimum number of cuts required to partition the substring into palindromes. The values of this function will be stored in the cells of the array . Therefore, the solution to the problem will be .
Note that , as a string consisting of a single character is already a palindrome.
To compute , cut the substring into two parts: and . Recursively solve the problems on the strings and . Look for the value of that minimizes the sum . The term in the sum represents the single cut made between the characters and . Thus, we obtain the following recurrence relation:
Example
For example, for the string "" consisting of characters, we have:
The sum takes its minimum value at :
Since the substrings "" and "" are palindromes, .
Algorithm implementation
Define the constants, the input string , and the arrays.
#define MAX 1001 #define INF 0x3F3F3F3F int dp[MAX][MAX], pal[MAX][MAX]; string s;
The function checks whether the substring is a palindrome. The substring is a palindrome if and is a palindrome. The values of are stored in the cells of the array .
int IsPal(int i, int j) { if (i >= j) return pal[i][j] = 1; if (pal[i][j] != -1) return pal[i][j]; return pal[i][j] = (s[i] == s[j]) && IsPal(i + 1, j - 1); }
The function returns the minimum number of cuts required to partition the substring into palindromes.
int f(int i, int j) {
If , the substring consists of a single character, and no cuts are needed. If , the substring is considered empty, and no cuts are required.
if (i >= j) return 0;
If the value is already computed, return the stored value from the .
if (dp[i][j] != INF) return dp[i][j];
If the substring is a palindrome, there is no need to make any cuts. In this case, the minimum number of cuts is .
if (IsPal(i, j)) return dp[i][j] = 0;
Cut the substring into two parts: and . Then, recursively solve the problems for both parts: and . Find the value of for which the sum is minimized.
for (int k = i; k < j; k++) dp[i][j] = min(dp[i][j], f(i, k) + f(k + 1, j) + 1);
Return the answer .
return dp[i][j]; }
The main part of the program. Read the input string.
cin >> s;
Initialize the arrays.
memset(dp, 0x3F, sizeof(dp)); memset(pal, -1, sizeof(pal));
Compute and print the answer.
res = f(0, s.size() - 1); cout << res << endl;