CodeChef:Girl Friend and String Gift(dp)

Chef's Girl Friend has given him a unique gift. She has given him a string S. Chef being a gentleman wants to return her gift in a unique way. He wants to break the string he has received into some number of substrings so that each substring is a palindrome. However he does not want break the string into too many substrings, otherwise the average size of his strings will become small. What is the minimum number of substrings in which the given string can be broken so that each substring is a palindrome.

Tips:

Refer http://en.wikipedia.org/wiki/Palindrome for the definition of a "palindrome"

Input

Input description.

  • The first line of the input contains an integer T denoting the number of test cases. The description of T test cases follows:
  • The first line of each test case contains a single integer N denoting the number of alphabets in the given string. The second line contains the given string.

Output

For each test case output a single integer the answer to the given test case. Print answer for each test case on a separate line.

Constraints

All characters in the given string are upper case English alphabets.

  • 1 ≤ T ≤ 10
  • 1 ≤ |S| ≤ 5000

Example

Input:

1 7 ABCCBDA
Output: 4

Explanation

Example case 1. The given string can be broken into "A" , "BCCB" , "D" , "A". It can be verified that you can't break the given string into less than 4 substrings such that each substring in a palindrome.

Scoring

Subtask 1: (15 points):

  • 1 ≤ |S| ≤ 20

Subtask 2: (25 points):

  • 1 ≤ |S| ≤ 250

Subtask 1: (60 points):

  • 1 ≤ |S| ≤ 5000
题意:给个字符串,问最少可以分成几个连续的回文子串。

思路:预处理每个回文串的位置,dp一下即可。

# include <bits/stdc++.h>
using namespace std;
typedef long long LL;
char s[5003];
int dp[5003];
vector<int>g[5003];
int main()
{
    int t, n;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        scanf("%s",s+1);
        memset(dp, 0x3f, sizeof(dp));
        dp[0] = 0;
        for(int i=1; i<=n; ++i) g[i].clear();
        for(int i=1; i<=n; ++i)
        {
            int j=i, k=i;
            for(; j>0&&k<=n; --j,++k)
            {
                if(s[j]!=s[k]) break;
                g[k].emplace_back(j);
            }
        }
        for(int i=1; i<n; ++i)
        {
            if(s[i] != s[i+1]) continue;
            int j=i, k=i+1;
            for(; j>0&&k<=n; --j,++k)
            {
                if(s[j]!=s[k]) break;
                g[k].emplace_back(j);
            }
        }
        for(int i=1; i<=n; ++i)
            for(auto j : g[i])
                dp[i] = min(dp[i], dp[j-1]+1);
        printf("%d\n",dp[n]);
    }
    return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值