来自julyc的新年求助

点击打开链接

Description

在2.14(情人节)的午夜,kkun作为一只程序猿并不难过,并且向单身狗julyc发动了嘲讽技能:

TIM图片20180214210914.png

julyc非常伤心,因为作为一只咸鱼直到年前都没有做完boss的任务,所以也没有时间去找学妹加强交流,因此他决定向各位请求帮助,而对于帮助julyc解决问题的小伙伴julyc就会偷偷告诉他们学姐cfenglv的qq啦。。

回文串划分就是将一个字符串划分为若干字串,并且每个字串都是一个回文串。

例如,字符串“ABACABA”可以有几种不同的划分方式,例如{"A","B","A","C","A","B","A"}, {"A","BACAB","A"}, {"ABA","C","ABA"}, or {"ABACABA"}。

julyc的任务是将给定字符串,确定其得到最少子串数量的回文串划分方式的子串数量。

Input

输入第一行包含一个整数T(T<=40),代表测试数据组数。每组测试数据中包含一个只包含大写字母的非空字符串s(length(s)<=1000)

Output

对于每组测试数据,你们应该输出测试数据组数跟答案。每组输出占一行。

Sample Input 1

4
AAAA
ABCDEFGH
QWERTYTREWQWERT
ABACCC

Sample Output 1

Case 1: 1
Case 2: 8
Case 3: 5
Case 4: 2

Hint

对于第三个样例,最少子串数的分割方案为:“QWERTYTREWQ”,“W”,“E”,“R”,“T”,分成了五个回文串

对于第四个样例,最少子串数的分割方案为:“ABA”,“CCC”,分成了两个回文串

#include<cstdio>
#include<cstring>
#include<algorithm>
#define bug(x) printf("%d***\n",x)
typedef long long ll;
using namespace std;

const int maxn=1010;
char str[maxn];
int dp[maxn][maxn];
int f[maxn]; 
/*
错了两个地方, 第一个是走的方向不对,我们没有实现已知的状态的获取 
               第二个就是我们不知道这个字符串是不是回文串,事实就是只要dp[i][j]=1,的话
			   就说明它是回文串 
*/

int main(){
	int n;
	scanf("%d",&n);
	int T=1;
	while(n--){
		scanf(" %s",str);
		int len=strlen(str);
		memset(dp,0,sizeof(dp));
		for(int j=0;j<len;j++){
			for(int i=j;i>=0;i--){
				if(i==j){
					dp[i][j]=1;continue;
				}
				if(i+1==j){
					dp[i][j]=str[i]==str[j]?1:2;continue;
				}
				if(dp[i+1][j-1]==1&&str[i]==str[j]){
					dp[i][j]=1;continue;
				}
				dp[i][j]=min(dp[i+1][j],dp[i][j-1])+1;
				/*for的缺点  超时  溢出 ,但是思路简单清晰 
				dp[i][j]=dp[i+1][j]+1;
				for(int k=i+1;k<j;k++)
					dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]);
				dp[i][j]=min(dp[i][j],dp[i][j-1]+1);
				for(int k=j-1;k>i;k--)
					dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]);
				*/
			}
		}
		/*
		这个循环真的是太牛了,把我们的每次精确的更新,都放到最后
		换一句话说,我们只需要判断哪些是回文的字符串,然后再最后枚举就行了
		如果在过程中每次都更新的话,我们指定超时 
		*/
		for(int j=0;j<len;j++){
			if(j==0) f[j]=1;
			else   f[j]=f[j-1]+1;
			for(int i=j-1;i>=0;i--)
				if(dp[i][j]==1)
					f[j]=min(f[j],f[i-1]+1); 
		}
		printf("Case %d: %d\n",T++,f[len-1]);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值