8633 回文划分
该题有题解
时间限制:1000MS 内存限制:1000K
提交次数:169 通过次数:63
题型: 编程题 语言: C++;C
Description
我们说一个字符串是回文串,那么意味着这个串从两边读起来的字母都是一样的。例如racecar是回文串,
然而fastcar则不是。
对一个串的划分意思是将一个串划分为若干个部分。例如,racecar可以划分为race 和car两部分。给出
一个串,要把这个串划分为若干个回文串,那么至少要把这个串划分为多少部分?
例如
'racecar’已经是回文串,划分为1 个部分即可(这个部分就是racecar)。
‘fastcar’ 需要被划分为七个部分 (‘f’, ‘a’, ‘s’, ‘t’, ‘c’, ‘a’, ‘r’)。根据回文串的定义,单个字母也是回文串。
‘aaadbccb’ 分成可以被分为三个回文串 (‘aaa’, ‘d’, ‘bccb’)。找不到更少的划分方法。
输入格式
输入的第一行是数字T,表示输入文件含有T个CASE。之后有T行,每行有一个长度不大于1000的字
符串,全部由小写字母组成,中间没有空格。
输出格式
对于每个CASE,输出一个数字,表示对该字符串的回文串最小划分。
输入样例
3
racecar
fastcar
aaadbccb
输出样例
1
7
3
提示
来源
PKKJ @ 07 GIS 1
#define _CRT_SECURE_NO_WARNINGS
#include<cstdio>
#include<iostream>
#include<vector>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
#include<cmath>
//dp数组 dp[i]含义是i以前的最小回文串数
int dp[1005];
//检查数组a中 bg到end是否为回文串
int check(char a[], int bg, int end) {
//双指针比对
for (; bg < end; bg++, end--) {
//如果不同返回0
if (a[bg] != a[end])return 0;
}
//回文串返回1
return 1;
}
int main(void) {
char a[1005];
int T;
cin >> T;
//多case
while (T--) {
//从a+1开始
cin >> (a + 1);
//字符串长度
int size = strlen(a + 1);
//遍历字符串数组
for (int i = 1; i <= size; i++) {
//先令当前dp[i]为上一格dp[i-1]+1 即i位不能和前面组成回文串的情况
dp[i] = dp[i - 1] + 1;
//定义j从1往后直到i 开始遍历 查j到i是否为字符串
for (int j = 1; j < i; j++) {
//如果为字符串
if (check(a, j, i)) {
//再比较当前dp[i]是否比 dp[j-1]+1 大
//dp[j-1]+1含义: dp[j-1](字符串j以前的dp最小值) +1(j到i组成回文串时j到i即为1)
//如果比原来的大就赋值
dp[i] = min(dp[j - 1] + 1, dp[i]);
//不能直接赋值第一个dp[j-1]就退出
//要比较两者大小
//abbaa就是一个例子
}
}
}
//最后输出dp[len]的值即为最小值
cout << dp[size]<<endl;
}
return 0;
}