ACM: uva 11584 -
2016-05-19 23:28
351 查看
Problem H: Partitioning by Palindromes
We say a sequence of characters is
a palindromeif 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' can be partitioned as ('aaa', 'd', 'bccb').
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.
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
题意: 将一段字符串划分为尽可能少的回文串, 输出最少能划分为多少个回文串.
解题思路:
1. 简单DP, 最朴素的做法就是枚举起点和终点, 判断这段是否为回文串, 时间复杂度O(n^3);
方程:
dp[i] = min(dp[i], dp[j-1]+1)
(j->i是回文串);
dp[i]表示: 前i个字符最少可以组成多少个回文串.
2. 还有方法可以缩小时间复杂度, 就是直接判断j->i是否是回文串, 时间复杂度O(n^2);
可以设flag[i][j]: 以str[j]开始的长度为i的字符串是否为回文串.
代码:
O(n^3)
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
#define MAX 1005
const int INF = (1<<29);
int n;
int dp[MAX];
char str[MAX];
inline int min(int a, int b)
{
return a < b ? a : b;
}
bool judge(int left, int right)
{
for(int i = left, j = right; i <=
j; ++i, --j)
if( str[i] != str[j] ) return
false;
return true;
}
int main()
{
// freopen("input.txt", "r", stdin);
scanf("%d", &n);
int i, j;
while(n--)
{
scanf("%s", str+1);
int len = strlen(str+1);
for(i = 1; i <=
len; ++i)
dp[i] =
INF;
dp[0] = 0;
for(i = 1; i <=
len; ++i)
{
for(j = 1; j
<= i; ++j)
{
if(
judge(j, i) )
dp[i]
= min(dp[i], dp[j-1]+1);
}
}
printf("%d\n",
dp[len]);
}
return 0;
}
O(n^2)
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
#define MAX 1005
const int INF = (1<<29);
char str[MAX];
int dp[MAX];
bool flag[MAX][MAX]; //flag[i][j]: 长度为i, 从str[j]开始有一段回文串
inline int min(int a, int b)
{
return a < b ? a : b;
}
void init(int len)
{
memset(flag, false, sizeof(flag));
int i, j;
for(i = 1; i <= len; ++i)
flag[1][i] = true;
if(len == 1) return ;
for(i = 1; i <= len-1;
++i)
if(str[i] == str[i+1])
flag[2][i]
= true;
for(i = 3; i <= len; ++i)
{
for(j = 1; j <=
len-i+1; ++j)
{
if(flag[i-2][j+1]
&& str[j] == str[j+i-1])
flag[i][j]
= true;
}
}
}
int main()
{
// freopen("input.txt", "r", stdin);
int caseNum, i, j;
scanf("%d", &caseNum);
while(caseNum--)
{
scanf("%s", str+1);
int len = strlen(str+1);
init(len);
for(i = 1; i
<= len; ++i) dp[i] = INF;
dp[0] = 0;
for(i = 1; i <=
len; ++i)
{
for(j = 1; j
<= i; ++j)
{
if(
flag[j][i-j+1] )
dp[i]
= min(dp[i], dp[i-j]+1);
}
}
printf("%d\n", dp[len]);
}
return 0;
}
We say a sequence of characters is
a palindromeif 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' can be partitioned as ('aaa', 'd', 'bccb').
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.
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
题意: 将一段字符串划分为尽可能少的回文串, 输出最少能划分为多少个回文串.
解题思路:
1. 简单DP, 最朴素的做法就是枚举起点和终点, 判断这段是否为回文串, 时间复杂度O(n^3);
方程:
dp[i] = min(dp[i], dp[j-1]+1)
(j->i是回文串);
dp[i]表示: 前i个字符最少可以组成多少个回文串.
2. 还有方法可以缩小时间复杂度, 就是直接判断j->i是否是回文串, 时间复杂度O(n^2);
可以设flag[i][j]: 以str[j]开始的长度为i的字符串是否为回文串.
代码:
O(n^3)
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
#define MAX 1005
const int INF = (1<<29);
int n;
int dp[MAX];
char str[MAX];
inline int min(int a, int b)
{
return a < b ? a : b;
}
bool judge(int left, int right)
{
for(int i = left, j = right; i <=
j; ++i, --j)
if( str[i] != str[j] ) return
false;
return true;
}
int main()
{
// freopen("input.txt", "r", stdin);
scanf("%d", &n);
int i, j;
while(n--)
{
scanf("%s", str+1);
int len = strlen(str+1);
for(i = 1; i <=
len; ++i)
dp[i] =
INF;
dp[0] = 0;
for(i = 1; i <=
len; ++i)
{
for(j = 1; j
<= i; ++j)
{
if(
judge(j, i) )
dp[i]
= min(dp[i], dp[j-1]+1);
}
}
printf("%d\n",
dp[len]);
}
return 0;
}
O(n^2)
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
#define MAX 1005
const int INF = (1<<29);
char str[MAX];
int dp[MAX];
bool flag[MAX][MAX]; //flag[i][j]: 长度为i, 从str[j]开始有一段回文串
inline int min(int a, int b)
{
return a < b ? a : b;
}
void init(int len)
{
memset(flag, false, sizeof(flag));
int i, j;
for(i = 1; i <= len; ++i)
flag[1][i] = true;
if(len == 1) return ;
for(i = 1; i <= len-1;
++i)
if(str[i] == str[i+1])
flag[2][i]
= true;
for(i = 3; i <= len; ++i)
{
for(j = 1; j <=
len-i+1; ++j)
{
if(flag[i-2][j+1]
&& str[j] == str[j+i-1])
flag[i][j]
= true;
}
}
}
int main()
{
// freopen("input.txt", "r", stdin);
int caseNum, i, j;
scanf("%d", &caseNum);
while(caseNum--)
{
scanf("%s", str+1);
int len = strlen(str+1);
init(len);
for(i = 1; i
<= len; ++i) dp[i] = INF;
dp[0] = 0;
for(i = 1; i <=
len; ++i)
{
for(j = 1; j
<= i; ++j)
{
if(
flag[j][i-j+1] )
dp[i]
= min(dp[i], dp[i-j]+1);
}
}
printf("%d\n", dp[len]);
}
return 0;
}
相关文章推荐
- ACM: uva 1468 - Restaurant
- ACM: poj 3972 -&n…
- jquery 1.6 后 checkbox 使用attr("checked"),undefined.
- ACM: poj 2786 -&n…
- ACM: uva 1432 -&n…
- ACM: uva 1451 - Average
- ACM: uva 10391 - Compound Words
- ACM: uva 10763 -&…
- ACM: uva 10125 - Sumsets
- Java发展历史
- ACM: uva 10827 -&…
- ACM: uva 1325 -&n…
- Iwfu-贝塞尔曲线
- ACM: uva 11389 -&…
- ACM: LA 3266 -&nb…
- ACM: uva 1467 - Installations
- ACM: uva 1450 - Airport
- ACM: uva 1335 - Beijing Guards
- ACM: uva 1276 - Network
- Python - pyqt 和 opencv