1044 - Palindrome Partitioning(记忆化DP)

A palindrome partition is the partitioning of a string such that each separate substring is a palindrome.

For example, the string “ABACABA” could be partitioned in several different ways, such as {“A”,”B”,”A”,”C”,”A”,”B”,”A”}, {“A”,”BACAB”,”A”}, {“ABA”,”C”,”ABA”}, or {“ABACABA”}, among others.

You are given a string s. Return the minimum possible number of substrings in a palindrome partition of s.

Input
Input starts with an integer T (≤ 40), denoting the number of test cases.

Each case begins with a non-empty string s of uppercase letters with length no more than 1000.

Output
For each case of input you have to print the case number and the desired result.

Sample Input
Output for Sample Input
3
AAAA
ABCDEFGH
QWERTYTREWQWERT
Case 1: 1
Case 2: 8
Case 3: 5

把一个字符串分割成几个部分,要求每个部分都是回文串,问最少分成几个部分。

先处理出哪些区间是回文区间,然后进行记忆化搜索(搜索的时候要注意,只找满足l,i区间是回文的i进行记忆化,否则超时,至于这个剪枝,原因也很简单,因为不是回文也没有搜索的必要了),具体看代码。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#include<vector>
#include<algorithm>
#include<string>
#include<cmath>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<utility>
#include<sstream>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 1005;
int t;
char s[1005];
int dp[1005][1005];
bool leap[1005][1005];
int dfs(int l,int r)
{
    if(dp[l][r] != -1)return dp[l][r];
    if(leap[l][r])return dp[l][r] = 1;
    int ans = r - l + 1;
    for(int i = l;i < r;i++)
    {
        if(leap[l][i])
            ans = min(ans,1 + dfs(i + 1,r));
    }
    return dp[l][r] = ans;
}
int main()
{
    #ifdef LOCAL
    freopen("C:\\Users\\巍巍\\Desktop\\in.txt","r",stdin);
    //freopen("C:\\Users\\巍巍\\Desktop\\out.txt","w",stdout);
    #endif // LOCAL
    int kase = 1;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s",s);
        memset(leap,false,sizeof(leap));
        int len = strlen(s);
        for(int i = 0;i < len;i++)
        {
            leap[i][i] = true;
            for(int j = 1;i >= j && i + j < len;j++)
            {
                if(s[i - j] == s[i + j])
                    leap[i - j][i + j] = true;
                else
                    break;
            }
        }
        for(int i = 0;i < len - 1;i++)
        {
            if(s[i] == s[i + 1])
            {
                leap[i][i + 1] = true;
                for(int j = 1;i >= j && i + 1 + j < len;j++)
                {
                    if(s[i - j] == s[i + 1 + j])
                        leap[i - j][i + 1 + j] = true;
                    else
                        break;
                }
            }
        }
        memset(dp,-1,sizeof(dp));
        printf("Case %d: %d\n",kase++,dfs(0,len - 1));
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值