Baseline Time Limit: 1 second Space Limit: 131072 KB Score: 40
Difficulty: Level 4 Algorithm Questions
There is a string S, find the minimum number of palindromes that S can be divided into.
For example: abbaabaa, there are many ways to divide.
a|bb|aabaa - 3 palindromes
a|bb|a|aba|a - 5 palindromes
a|b|b|a|a|b|a|a - 8 palindromes
Among them, the first division method has the least number of divisions.
Input
Input string S (length of S <= 5000).
Output
Output the minimum number of divisions.
Input example
father
Output example
3
Idea: dp[i] represents the minimum number of palindrome strings that can be divided into i.
dp[i] = min( dp[i] , dp[j-1]+1); (when ji is a palindrome).
First, use the Manacher algorithm to preprocess to get the P[i] array. When performing dp, take the p[pos] value of the position between i and j. If p[pos]+pos >= i or j==i, then it means that ji This paragraph is a palindrome.
(Manacher's algorithm p[i]+i-1 is the rightmost position of the center of each palindrome, and this position is the '#' sign.)
Code:
#include <bits/stdc++.h> using namespace std; const int AX = 1e4+66; int p[AX]; int dp[AX]; char s[AX]; int main(){ cin >> s ; int len = strlen(s); for( int i = len ; i >= 0 ; i-- ){ s[2*i+2] = s[i]; s[2*i+1] = '#'; } s[0] = '$'; int id = 0 , mx = 0 ; for( int i = 2 ; i < 2 * len + 1 ; i++ ){ if( p[id] + id > i ){ p[i] = min( p[id] + id - i , p[2*id-i] ); }else p[i] = 1; while( s[i - p[i]] == s[i+p[i]] ) p[i] ++; if( mx < p[i] + i ){ mx = p[i] + i; id = i; } } dp[0] = 1; for( int i = 1 ; i < len ; i++ ){ dp[i] = i + 1 ; for( int j = 0 ; j <= i ; j++ ){ int tm_i = 2 * i + 2; int tm_j = 2 * j + 2; int pos = ( tm_i + tm_j ) >> 1 ; if( p[pos] + pos - 1 > tm_i || i == j ){ dp[i] = min( dp[i] , dp[j-1] + 1 ); } } } cout << dp[len-1] << endl; return 0 ; }