动态规划——划分为回文串

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/LSC_333/article/details/77883273

题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2631


题意:

输入一个字符串,问最少可以将它划分成多少个回文串。


思路:

可以设置dp[i]为从第一个字符到第i个字符之间最少可以划分的回文串,然后设1<=j<=i,如果s[j+1]~s[i]是回文串那么dp[i]=min(dp[j]+1)


O(n的三次方)写法,20ms

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <stack>
#define INF 0x3f3f3f3f
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int maxn=1010;
char s[maxn];
int dp[maxn];
int len;
bool check(int a, int b)
{
    int left=a, right=b;
    while(a<b)
    {
        if(s[a]!=s[b])
            return false;
        a++; b--;
    }
    return true;
}
int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%s", s+1);
        len=strlen(s+1);
        memset(dp, 0, sizeof(dp));
        for(int i=1; i<=len; i++)
        {
            dp[i]=i+1;
            for(int j=1; j<=i; j++)
                if(check(j, i))
                    dp[i]=min(dp[i], dp[j-1]+1);
        }
        printf("%d\n", dp[len]);
    }
    return 0;
}


O(n方)写法,事先打表将回文串标记,30ms。。。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <stack>
#define INF 0x3f3f3f3f
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int maxn=1010;
bool wtf[maxn][maxn];
int dp[maxn];
char s[maxn];
int len;
void init()
{
    memset(wtf, 0, sizeof(wtf));
    for(int i=1; i<=len; i++)
        wtf[1][i]=true;
    if(len==1)
        return;
    for(int i=1; i<len; i++)
        if(s[i]==s[i+1])
            wtf[2][i]=true;
    for(int i=3; i<=len; i++)
        for(int j=1; j<=len-i+1; j++)
            if(s[j]==s[j+i-1]&&wtf[i-2][j+1])
                wtf[i][j]=true;
}
int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%s", s+1);
        len=strlen(s+1);
        init();
        for(int i=1; i<=len; i++)
            dp[i]=INF;
        dp[0]=0;
        for(int i=1; i<=len; i++)
        {
            for(int j=1; j<=i; j++)
                if(wtf[j][i-j+1])
                    dp[i]=min(dp[i], dp[i-j]+1);
        }
        printf("%d\n", dp[len]);
    }
    return 0;
}


估计是数据比较弱,导致O(n方)的写法比O(n的三次方)要慢。。。

猜你喜欢

转载自blog.csdn.net/LSC_333/article/details/77883273