LightOJ 1044 Palindrome Partitioning(简单字符串DP)

Posted stxy-ferryman

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LightOJ 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

3

AAAA

ABCDEFGH

QWERTYTREWQWERT

Sample Output

Case 1: 1

Case 2: 8

Case 3: 5

 

题意:给出一个字符串,将该字符串切割成若干个回文串,使切割后的回文串数最小,求这个回文串数

 

题解:这道题其实在之前DP百题大过关中已经出现过了,复杂度是n^3的,今天写的时候突然糊出了n^2的做法,再记录一下

首先是状态转移方程的推导

f[i]表示1-i之间的最小分割数,很显然只有当i~j是回文串的时候i-1才能转移到j,贡献为1

所以状态转移方程为

f[j]=max{f[i-1]+1}(i~j为回文串)

这个转移方程是n^2的,但上次写的时候在里面加入了O(N)的回文串判断,复杂度变成了O(N^3)

如今想想,其实是不是回文串这东西是可以预处理的

枚举每一个中点,向两边拓展,可以在O(N^2)中处理出每一段i~j是否是回文串

然后就有了O(N^2)复杂度的DP

 

代码如下:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

int c[1010][1010],n,f[1010];
char s[1010];

void get(int l,int r)
{
    while(l>0&&r<=n)
    {
        if(s[l]==s[r])
        {
            c[l][r]=1;
        }
        else
        {
            return ;
        }
        l--;
        r++;
    }
}

int main()
{
    int t,ttt=0;
    scanf("%d",&t);
    while(t--)
    {
        ttt++;
        memset(f,0x3f,sizeof(f));
        memset(c,0,sizeof(c));
        scanf("%s",s+1);
        n=strlen(s+1);
        for(int i=1; i<=n; i++)
        {
            get(i,i);
            get(i,i+1);
        }
        f[0]=0;
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=i; j++)
            {
                if(c[j][i])
                {
                    f[i]=min(f[i],f[j-1]+1);
                }
            }
        }
        printf("Case %d: %d
",ttt,f[n]);
    }

}

 

 

大佬们的常数都好优越啊,N^3跑的都比N^2快qwq

以上是关于LightOJ 1044 Palindrome Partitioning(简单字符串DP)的主要内容,如果未能解决你的问题,请参考以下文章

Palindrome Partitioning LightOJ - 1044(回文串最小分割数,O(n^2)预处理子串是否回文)

Light oj 1044 - Palindrome Partitioning(区间dp)

lightoj1044_区间dp

LightOJ 1007 Mathematically Hard

3.回文数(Palindrome.cpp)

LightOJ1030(数学概率与期望)