http://lightoj.com/volume_showproblem.php?problem=1044
A palindrome partition is the partitioning of a string such that each separate substring is a palindrome.
For example, the string "ABACABA" could be partitioned in several different ways, such as {"A","B","A","C","A","B","A"}, {"A","BACAB","A"}, {"ABA","C","ABA"}, or {"ABACABA"}, among others.
You are given a string s. Return the minimum possible number of substrings in a palindrome partition of s.
Input starts with an integer T (≤ 40), denoting the number of test cases.
Each case begins with a non-empty string s of uppercase letters with length no more than 1000.
For each case of input you have to print the case number and the desired result.
Sample Input |
Output for Sample Input |
3 AAAA ABCDEFGH QWERTYTREWQWERT |
Case 1: 1 Case 2: 8 Case 3: 5 |
思路:刚开始想到从第i个字符串往前判断有多少个回文串,但是时间复杂度为O(n^3),优化一下,遍历真个字符串,判断lr之间有多少个字符串,然后dp就ok了
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <queue> #include <algorithm> using namespace std; #define N 1010 #define INF 0x3f3f3f3f #define MOD 2009 #define met(a, b) memset (a, b, sizeof(a)) typedef long long LL; int vis[N][N]; int main () { int n, dp[N], nCase = 1; char str[N]; scanf ("%d", &n); while (n--) { met (str, 0); met (vis, 0); scanf ("%s", str+1); for (int i=0; i<=N; i++) dp[i] = INF; dp[0] = 0; int len = strlen (str+1); for (int i=1; i<=len; i++) { for (int l=1; l+i-1<=len; l++) { int r = l+i-1; if (str[l] == str[r]) { if (l+1 > r-1) vis[l][r] = 1; else vis[l][r] = vis[l+1][r-1]; } } } for (int i=1; i<=len; i++) { dp[i] = dp[i-1] + 1; for (int j=i-1; j>=1; j--) { if (vis[j][i]) dp[i] = min (dp[i], dp[j-1]+1); } } printf ("Case %d: %d\n", nCase++, dp[len]); } return 0; }