URAL 1635. Mnemonics and Palindromes

给出一字符串,将其分割成一系列回文串,子串数量应尽可能的少。

由于昨天刚做了一个类似的题,看完题的第一思路就是枚举区间,时间复杂度o(n^3),妥妥的TLE了。然后开始想各种优化,均无果。倒是顺便看了一下四边形不等式优化。

然后又换了一种思路时间复杂度降到了o(n^2) 。幸好大部分代码还能用,数组的下标运算还错了一次. . . .

if(Is_Palindrome( i , j ) )

ans[ j ] =  min(ans[ j ] , ans[ i -1]+1);

ans[ i ] 表示从1 到 i 的最优方案。

#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
#include <stack>

#pragma comment(linker, "/STACK:1024000000");
#define LL long long int
#define ULL unsigned long long int
#define _LL __int64
#define INF 0x3f3f3f3f
#define Mod 1000000009

using namespace std;

char s[4010];

bool dp[4001][4001];

int ans[4010];

int di[4010];

void Output(int l)
{
    if(l == 0)
        return ;

    Output(di[l]);

    if(di[l] != 0)
        printf(" ");

    for(int i = di[l]+1;i <= l; ++i)
    {
        printf("%c",s[i]);
    }
}

int main()
{
    int l,i,j,h,e;

    scanf("%s",s+1);

    l = strlen(s+1);

    memset(dp,false,sizeof(dp));

    for(i = 1;i <= l; ++i)
    {
        dp[i][i] = true;
        h = i-1;
        e = i+1;

        while(1 <= h && e <= l && s[h] == s[e])
        {
            dp[h][e] = true;
            h--,e++;
        }

        h = i,e = i+1;

        while(1 <= h && e <= l && s[h] == s[e])
        {
            dp[h][e] = true;
            h--,e++;
        }
    }

    memset(ans,INF,sizeof(ans));

    ans[0] = 0;

    di[1] = 0;

    for(i = 1;i <= l; ++i)
    {
        for(j = i;j >= 1; --j)
        {
            if(dp[j][i])
            {
                if(ans[i] > ans[j-1]+1)
                {
                    ans[i] = ans[j-1]+1;
                    di[i] = j-1;
                }
            }
        }
    }

    printf("%d\n",ans[l]);

    Output(l);

    puts("");

    return 0;
}

你可能感兴趣的:(URAL 1635. Mnemonics and Palindromes)