UVa11584划分成回文串

Posted rlddd

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UVa11584划分成回文串相关的知识,希望对你有一定的参考价值。

题目描述

 给一个字符串, 要求把它分割成若干个子串,使得每个子串都是回文串。问最少可以分割成多少个。 字符串长度不超过1000。
例如: 
“racecar”本身就是回文串,答案为1 
“fastcar”,答案为7,分成的7个回文串为"f", "a", "s", "t", "c", "a", "r" 
“aaadbccb”,答案为3,分成的3个回文串为"aaa", "d", "bccb"


输入

第一行一个数T。接下来T行,每行一个字符串。


输出

对于每个字符串输出答案。


样例输入

3

racecar

fastcar

aaadbccb


样例输出

1

7

3

 



题解

dp[i] 为字符串中 1~i 划分成最少回文串的个数。则:

            dp[ i ]=min( dp[ j ] + 1 )         其中,s[  j+1 -> i ] 为回文串

于是我们发现时间复杂度来到了O(n3),不够优秀。考虑降低复杂度,我们用O(n2)的时间预处理出 s[ i --> j ] 是否为回文串

然后总时间复杂度降为 O(n2)。

 

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long

const int maxn=1000+10;

char a[maxn];
int dp[maxn],l,lef,rig;
bool p[maxn][maxn];

template<typename T>void read(T& aa) {
    char cc; ll ff;aa=0;cc=getchar();ff=1;
    while((cc<0||cc>9)&&cc!=-) cc=getchar();
    if(cc==-) ff=-1,cc=getchar();
    while(cc>=0&&cc<=9) aa=aa*10+cc-0,cc=getchar();
    aa*=ff;
}

int main(){
    memset(dp,127,sizeof(dp));
    memset(p,false,sizeof(p));
    scanf("%s",a+1);
    l=strlen(a+1);
    for(int i=1;i<=l;i++){
        lef=i;rig=i;
        while(lef>0&&rig<=l){
            if(a[lef]==a[rig])
            p[lef][rig]=true;
            else break;
            lef--;rig++;
        }
    }
    for(int i=1;i<l;i++){
        lef=i;rig=i+1;
        while(lef>0&&rig<=l){
            if(a[lef]==a[rig])
            p[lef][rig]=true;
            else break;
            lef--;rig++;
        }
    }
    dp[1]=1;dp[0]=0;
    for(int i=2;i<=l;i++)
    for(int j=0;j<i;j++){
        if(p[j+1][i])
        dp[i]=min(dp[i],dp[j]+1);
    }
    cout<<dp[l]<<endl;
    return 0;
}

 










以上是关于UVa11584划分成回文串的主要内容,如果未能解决你的问题,请参考以下文章

UVa11584划分成回文串

uva11584

UVA 11584 DP

Partitioning by Palindromes UVA - 11584

uva 11584 Partitioning by Palindromes 线性dp

UVa 11584 - Partitioning by Palindromes(线性DP + 预处理)