您的位置:首页 > 其它

Scau 8633 回文划分 mancher + dp

2015-10-26 22:06 267 查看
时间限制:1000MS  内存限制:1000K
提交次数:169 通过次数:63

题型: 编程题   语言: G++;GCC

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

dp[i]表示前i个字符最少能被划分为回文串的个数

转移就很简单了:dp[i] = min(dp[j - 1]) + 1; 其中 1 <= j <= i 并且 (s[j]~s[i])是回文串

直接算复杂度是O(n^3),显然不行,可以用mancher预处理出vis[i][j], 表示(s[i]~s[j])是否是回文串

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 1005;
char s
, str[N << 1];
bool vis

;
int dp
, p[N << 1], len;
void get(int n)
{
int mx = 0, id = 0;
for(int i = 0; i < n; ++i)
{
p[i] = mx > i ? min(p[2 * id - i], mx - i) : 1;
while(str[i + p[i]] == str[i - p[i]]) p[i]++;
if(i + p[i] > mx) {
mx = i + p[i];
id = i;
}
}
}
void pre(int n)
{
memset(vis, false, sizeof vis);
for(int i = 2; i < n; ++i)
{
if(i & 1) {
int st = i - 1;
int ed = i + 1;
int to = i - p[i] + 1;
while(st >= to) { vis[st >> 1][ed >> 1] = true; st -= 2; ed += 2; }
}else {
int id = i >> 1;
vis[id][id] = true;
int st = i - 2;
int ed = i + 2;
int to = i - p[i] + 1;
while(st >= to) { vis[st >> 1][ed >> 1] = true; st -= 2; ed += 2; }
}
}
}
void init()
{
int n = 0;
str[n++] = '$';
str[n++] = '#';
for(int i = 0; i < len; ++i) {
str[n++] = s[i];
str[n++] = '#';
}
str
= 0;
get(n);
pre(n);

}
void solve()
{
dp[0] = 0;
for(int i = 1; i <= len; ++i)
{
dp[i] = 0x3f3f3f3f;
for(int j = 1; j <= i; ++j) if(vis[j][i])
dp[i] = min(dp[i], dp[j - 1] + 1);
}
printf("%d\n", dp[len]);
}
int main()
{
int _; scanf("%d", &_);
while(_ --)
{
scanf("%s", s);
len = strlen(s);
init();
solve();
}
return 0;
}
  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: