UVA-11584-Partitioning by Palindromes(区间DP 最小回文串数量)

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’ can 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

题意:给定一个字符串,找到字符串中回文子串的最小数量。

思路:枚举i~j并判断是否为回文子串,如果是的话状态转移DP[i]=min(DP[i],DP[j-1]+1)
时间复杂度O(N*N*N)
代码

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<math.h>
#include<string>
using namespace std;
//最小回文串数量
const int maxn=1005;
const int INF=0x3f3f3f3f;
int DP[maxn];//以i结尾的最小回文串数量
char str[maxn];
int main()
{
    int N;
    scanf("%d",&N);
    while(N--)
    {
        memset(str,'\0',sizeof(str));
        memset(DP,0x3f3f,sizeof(DP));
        scanf("%s",str+1);
        DP[0]=0;
        int len=strlen(str+1);
        for(int i=1; i<=len; i++)
        {
            for(int j=1; j<=i; j++)
            {
                bool is_huiwen=true;//从j到i是不是回文串
                for(int k=j,t=i; k<=t; k++,t--)
                    if(str[k]!=str[t])
                    {
                        is_huiwen=false;
                        break;
                    }
                if(is_huiwen==true)
                {
                    DP[i]=min(DP[j-1]+1,DP[i]);
                }
            }
        }
        printf("%d\n",DP[len]);
    }
    return 0;
}

还可以提前预处理出DP[i][j]代表以i开头长度为j的字符串是否为回文串。
查询时候和上面一样枚举i~j,直接通过预处理结果就可以判断出是否为回文。
时间复杂的O(N*N),不过常数略大。

代码

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<math.h>
#include<string>
using namespace std;
//最小回文串数量
const int maxn=1005;
const int INF=0x3f3f3f3f;
bool DP[maxn][maxn];//标记以i开头长度为j的字符串是否为回文串
int result[maxn];//以i结尾的最小回文串数量
char str[maxn];
int main()
{
    int N;
    scanf("%d",&N);
    while(N--)
    {
        memset(result,0x3f,sizeof(result));
        memset(str,'\0',sizeof(str));
        memset(DP,false,sizeof(DP));
        scanf("%s",str+1);
        int len=strlen(str+1);
        for(int i=1; i<=len; i++)
            DP[i][1]=true;//以i开头长度为1的字符串是回文串
        for(int i=1; i<=len-1; i++)
            if(str[i]==str[i+1])
                DP[i][2]=true;//以i开头长度为2的字符串是回文串
        for(int j=3; j<=len; j++)//枚举长度
            for(int i=1; i<=len-j+1; i++)//枚举起点
                if(DP[i+1][j-2]==true&&str[i]==str[i+j-1])
                    DP[i][j]=true;//拓展回文串
        result[0]=0;
        for(int i=1; i<=len; i++)
            for(int j=1; j<=i; j++)
                if(DP[i-j+1][j]==true)
                    result[i]=min(result[i],result[i-j]+1);
        printf("%d\n",result[len]);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值