Timus 1635

令res[i][j]表示从i到j是否是回文串。

res[i][j]= (str[i]==str[j] && res[i+1][j-1]) ;

接下来是如何找最少个数回文串,令inum[i]表示从1到i至少有多少个回文串,再次用DP;

inum[i]=min(inum[j]+1),(其中res[j][i]==1,1<=j<i);

最后根据inum[i]的值寻找一种可行的方案。

O(n^2)的时间复杂度,O(n^2)的空间复杂度,网上还有更好的代码,竟然没有看懂

#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;
#define MAX 1234567890
char str[4010];
int res[4010][4010],start[4010],end[4010],inum[4010],step;
int work(int n)
{
    int i,j;
    for(i=1;i<=n;i++) res[i][i]=res[i][i-1]=1;
    for(j=1;j<=n;j++)
        for(i=j-1;i>0;i--)
            if(str[i]==str[j] && res[i+1][j-1]) res[i][j]=1; 
    return 0;
}
int GetMin(int n)
{
    int i,j;
    for(i=1;i<=n;i++)
    {
        inum[i]=i;
        for(j=0;j<i;j++)
            if(res[j+1][i]) inum[i]= inum[i] < inum[j]+1 ? inum[i] : inum[j]+1;
    }
    return inum[n];
}
int f(int s,int t)
{
    int i;
    for(i=s;i<=t;i++)
        printf("%c",str[i]);
    return 0;
}
int GetRes(int n)
{
    int i,j;
    stack <int> S1;
    stack <int> S2;
    i=n;
    while(i>0)
    {
        S2.push(i);
        for(j=i-1;j>0;j--)
        {
            if(res[j+1][i] && inum[j]+1==inum[i])
            {
                S1.push(j+1);
                break;
            }
        }
        i=j;
    }
    S1.push(1);
    f(S1.top(),S2.top());
    S1.pop(); S2.pop();
    while(!S1.empty())
    {
        printf(" ");
        f(S1.top(),S2.top());
        S1.pop(); S2.pop();
    }
    printf("\n");
    return 0;
}
int main()
{
    int l;
    while(scanf("%s",str+1)!=EOF)
    {
        l=strlen(str+1);
        step=l;
        memset(res,0,sizeof(res));
        work(l);
        printf("%d\n",GetMin(l));
        GetRes(l);
    }
    return 0;
}
posted @ 2012-05-01 16:16  书山有路,学海无涯  阅读(218)  评论(0编辑  收藏  举报