51nod 1154 回文串划分

基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题
 收藏
 关注
有一个字符串S,求S最少可以被划分为多少个回文串。
例如:abbaabaa,有多种划分方式。

a|bb|aabaa - 3 个回文串
a|bb|a|aba|a - 5 个回文串
a|b|b|a|a|b|a|a - 8 个回文串

其中第1种划分方式的划分数量最少。
Input
输入字符串S(S的长度<= 5000)。
Output
输出最少的划分数量。
Input示例
abbaabaa
Output示例
3


马拉车算法+DP

#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define MOD 1000000007
#define MX 5005

int n;
int len;
char temp[MX];
char str[MX*2];
int p[MX*2];
int dp[MX*2];

void Init()
{
    len = 0;
    str[len++]='@';
    str[len++]='#';
    n = strlen(temp);
    for (int i=0;i<n;i++)
    {
        str[len++]=temp[i];
        str[len++]='#';
    }
    memset(p,0,sizeof(p));
}

void Manacher()
{
    Init();
    int mx = 0, id =0;
    for (int i=1;i<len;i++)
    {
        p[i] = mx>i ? min(p[2*id-i],mx-i):1;
        while (str[i+p[i]]==str[i-p[i]]) p[i]++;
        if (i+p[i]>mx)
        {
            mx = i+p[i];
            id = i;
        }
    }
}
int main()
{
    while (scanf("%s",temp)!=EOF)
    {
        Manacher();

        for (int i=0;i<n;i++)
        {
            dp[i] = i+1; //初值
            int pos = (i+1)*2;
            for (int j=pos;j>=1;j--)
            {
                if(j+p[j]-2>=pos)
                {
                    int pre = (j-(pos-j))/2-1;
                    if (pre==0) dp[i]=1;
                    else dp[i]= min(dp[pre-1]+1,dp[i]);
                }
            }
        }
        printf("%d\n",dp[n-1]);
    }
    return 0;
}


posted @ 2017-10-21 15:31  Bryce1010  阅读(95)  评论(0编辑  收藏  举报