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;

}

你可能感兴趣的:(IM)