【Jason's_ACM_解题报告】Partitioning by Palindromes

Partitioning by Palindromes

We say a sequence of characters is a palindrome if it is the same written forwards and backwards. For example, ‘racecar’ is a palindrome, but ‘fastcar’ is not. 


A partition of a sequence of characters is a list of one or more disjoint non-empty groups of consecutive characters whose concatenation yields the initial sequence. For example, (‘race’, ‘car’) is a partition of ‘racecar’ into two groups.


Given a sequence of characters, we can always create a partition of these characters such that each group in the partition is a palindrome! Given this observation it is natural to ask: what is the minimum number of groups needed for a given string such that every group is a palindrome?


For example:
· ‘racecar’ is already a palindrome, therefore it can be partitioned into one group.
· ‘fastcar’ does not contain any non-trivial palindromes, so it must be partitioned as (‘f’, ‘a’, ‘s’, ‘t’, ‘c’, ‘a’, ‘r’).
· ‘aaadbccb’ c
an be partitioned as (‘aaa’, ‘d’, ‘bccb’).


Input
Input begins with the number n of test cases. Each test case consists of a single line of between 1 and 1000 lowercase letters, with no whitespace within.


Output
For each test case, output a line containing the minimum number of groups required to partition the input into groups of palindromes.


Sample Input
3
racecar
fastcar
aaadbccb


Sample Output
1
7
3


不要被题目的本身所迷惑,不要妄想在不知道如何进行动态规划求回文串的前提下去动态的维护回文串以及最小回文串的个数。

看到数据规模后,大胆的将问题抽离出来,预处理is_p[i][j]表示str[i][j]是否为为回文串,然后设状态转移方程dp[i]=min{dp[j]+1|is_p[j+1][i]==true}题目得解。



附代码如下:
#include<cstdio> 
#include<cstring>

#include<algorithm>

using namespace std;

#define MAXN (1000+5)
#define OO (0x7fffffff)

char str[MAXN];
bool is_p[MAXN][MAXN];
int dp[MAXN];

int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		scanf("%s",str+1);
		int n=strlen(str+1);
		memset(is_p,false,sizeof(is_p));
		for(int i=1;i<=n;i++){
			int j=0;
			while(1<=i-j&&i+j<=n&&str[i-j]==str[i+j]){
				is_p[i-j][i+j]=true;
				j++;
			}
			j=0;
			while(1<=i-j&&i+j+1<=n&&str[i-j]==str[i+j+1]){
				is_p[i-j][i+j+1]=true;
				j++;
			}
		}
		/*
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				printf("%d ",is_p[i][j]);
			}
			printf("\n");
		}
		//*/
		dp[0]=0;
		for(int i=1;i<=n;i++){
			dp[i]=OO;
			for(int j=0;j<i;j++){
				if(is_p[j+1][i])dp[i]=min(dp[i],dp[j]+1);
			}
		}
		
		printf("%d\n",dp[n]);
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值