Light oj 1044 Palindrome Partitioning

Light oj 1044

题目:要求将一个序列划分为最少个回文子串。

 

如果不加思索,想当然将局部问题F[i][j]定义为:从aiaj的子串可以划分的回文串最少个数;那么求F[i][j]需要枚举子区间,时间复杂度为O(n^3)

 

F[i]定义为:从ai到序列尾端的子串可以划分为的回文串的最少个数;

我们做完预处理:

a[i][j]1aiaj的序列是回文子串;a[i][j]=0,即表示不能形成回文子串;

O(n^2)就能完成!

我们不需要再求那些从aiaj的子串(aj不为序列末尾)可以划分的回文串最少个数,一样需要枚举左半部分,只是只有左半部为回文串才讨论划分。其它不为回文串的可能情况都会包含在仅划掉ai的情况里(ai本身形成回文串);

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <string.h>
#include <math.h>

using namespace std;

int F[1100][1100];
int g[1100];
char a[1100];
int dfs(int t,int len){
    if(t>len)return 0;
    int &k=g[t];
    if(k!=-1)return k;
    k=1e9;
    for(int i=t;i<=len;++i)
    {
        if(F[t][i]) k=min(k,dfs(i+1,len)+1);
    }
    return k;
}

int main(){
    int T;scanf("%d",&T);
    int kase=0;
    while(T--){
        memset(g,-1,sizeof(g));
        scanf("%s",a);
        int len=strlen(a);

        for(int i=1;i<=len;++i)
        {
            F[i][i]=1;
            F[i][i-1]=1;
        }
        for(int l=2;l<=len;++l){
            for(int i=1;i+l-1<=len;++i){
                int last=i+l-1;
                if(a[i-1]==a[last-1]&&F[i+1][last-1]==1)F[i][last]=1;
                else F[i][last]=0;
            }
        }
        printf("Case %d: %d\n",++kase,dfs(1,len));

        }

    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值