Partitioning by Palindromes UVA - 11584

 VOJ题目位置:UVA - 11584 

这道题主要是找到最小回文串的个数,我们可以把从1到达n个字符串看成从1到2,再从1到3等等到子阶段来解决,毫无疑问这样采用的是dp方法。

我们采用dp[i]表示前i个字符(下标从0到i-1)构成的字串的最小回文串的个数,由于dp[i]的第i个(下标为i-1)可能和前面的构成一个回文,所以得遍历从1到i-1的情况(设当前遍历的变量为j),如果下标j到i-1的子字符串为回文,则dp[i] = min(dp[i], dp[j] + 1);因为从j到i-1是一个回文字符串。

但是如何快速判断j到i-1是否为回文呢?可以采用预处理到方法,即若回文字符串为奇数个,则遍历字符串的中间i,设置变量j,一开始为0,然后逐渐加1,字符串左边就为i-j,右边就为i+j,每次j加一就相当于i往左右扩大了1个,判断此时是否为回文字符串,一直加到不为回文字符串为止;若为偶数个,则设定好中间两个左边为i,右边为i+j,j一开始为0,然后j逐渐加1,左边就为i-j+1,右边就为i+j。复杂度O(n2)

 

for(int i = 0; i < n; i++)
        {
            for(int j = 0; i - j >= 0 && i + j < n; j++)//奇数个情况,i为中间的下标,j为往左右两边扩张的个数,易得左边界为i - j, 右边界为i + j
            {
                if(temp[i - j] != temp[i + j])//如果此时扩张字符串后不为回文字符串了,因为一开始字符串只有一个字符必定为回文,
//然后每次扩张一个只需要判断左右边界是否相同即可,如果不相同则说明此时开始,以i为中心的子字符串现在以及之后都不会是回文的了。
break; else is_p[i - j][i + j] = true; } for(int j = 1; i - j + 1 >= 0 && i + j < n; j++)//偶数个情况,i为中间两个的左边下标,一开始j=1,i-j+1为左边界,i+j为右边界 { if(temp[i - j + 1] != temp[i + j]) break; else is_p[i - j + 1][i + j] = true; } }

 

完整代码:

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
char temp[1005];
bool is_p[1005][1005];
int dp[1005];
int main()
{
    int t, n;
    scanf("%d", &t);
    for(int cnt = 0; cnt < t; cnt++)
    {
        memset(is_p, 0, sizeof(is_p));
        scanf("%s", temp);
        n = strlen(temp);
        for(int i = 0; i < n; i++)
        {
            for(int j = 0; i - j >= 0 && i + j < n; j++)
            {
                if(temp[i - j] != temp[i + j])
                    break;
                else
                    is_p[i - j][i + j] = true;
            }
            for(int j = 1; i - j + 1 >= 0 && i + j < n; j++)
            {
                if(temp[i - j + 1] != temp[i + j])
                    break;
                else
                    is_p[i - j + 1][i + j] = true;
            }
        }
        for(int i = 0; i <= n; i++)
            dp[i] = i;//默认前i个的最大回文字符串个数就为字符串的个数
        for (int i = 1; i <= n; ++i)
        {
            for (int j = 0; j < i; ++j)
            {
                if(is_p[j][i - 1])
                    dp[i] = min(dp[i], dp[j] + 1);
            }
        }
        printf("%d\n", dp[n]);
    }
    return 0;
}

 

 

 
posted @ 2020-07-15 15:57  funforever  阅读(132)  评论(0编辑  收藏  举报