codeforces 835D 区间dp

本文介绍了一种使用区间动态规划(DP)的方法来计算字符串中不同长度的最大回文子串数量。通过构建二维DP数组,实现了对于任意长度的子串是否为回文串的有效判断,并统计了各种长度回文串的数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简单的区间dp
dp[i][j] 表示区间i-j的回文度数
转移方程就是在 si=sjdp[i+1][j1]>0 dp[i][j]=dp[i+1][(i+j)/2]+1

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<string>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cstring>
#define clr(x) memset(x,0,sizeof(x))
using namespace std;
#define LL long long
int dp[5005][5005];
int main()
{
    char str[5005];
    while(scanf("%s",str)!=EOF)
    {
        clr(dp);
        int len = strlen(str);
        int ans[5005] = {0};
        for(int i = 0;i<len;i++)
            dp[i][i] = 1,ans[1]++;
        for(int i = 1;i<len;i++)
        {
            for(int j = 0;j<len-i;j++)
            {
                if(i&1) // 偶数个
                {
                    if(i==1)
                    {
                        if(str[j]==str[j+i])
                        {
                            dp[j][j+i] = 2;
                            ans[2]++;
                        }
                    }
                    else
                    {
                        int l = j+1;
                        int r = j+i-1;
                        if(str[j] == str[j+i] && dp[l][r]>0)
                        {
                            dp[j][j+i] = dp[j][j+i/2]+1;
                            ans[dp[j][j+i]]++;
                        }
                    }
                }
                else // 奇数个
                {
                    int l = j+1;
                    int r = j+i-1;

                    if(str[j]==str[j+i] && dp[l][r]>0)
                    {
                        dp[j][j+i] = dp[j][j+i/2-1]+1;
                        ans[dp[j][j+i]]++;
                    }
                }
                //cout << j << " " << j+i << " num " << dp[j][j+i] << endl;
            }
        }
        //cout << dp[2][4] << endl;
        for(int i = len-1;i>=0;i--)
        {
            ans[i] = ans[i]+ans[i+1];
        }
        for(int i = 1;i<=len;i++)
        {
            if(i!=1)printf(" ");
            printf("%d",ans[i]);
        }
        printf("\n");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值