【区间DP】HDU 4632 Palindrome subsequence

本文详细解析了HDU4632题目,通过动态规划求解字符串中回文子序列的最大数量。介绍了状态转移方程,并提供了完整的C++代码实现,适合算法学习者深入理解动态规划思想。

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

 HDU 4632 Palindrome subsequence

题意:让找一个字符串中回文子序列的最大数量。

举两个栗子:

//aaa
/* len = 2 */
dp[1][2] = dp[1][1] + dp[2][2] + 1 = 3;
dp[2][3] = dp[2][2] + dp[3][3] + 1 = 3;
/* len = 3 */
dp[1][3] = dp[1][2] + dp[2][3] + 1 = 7;

//abcd
/* len = 2 */
dp[1][2] = dp[1][1] + dp[2][2] = 2;//这里没有减,其实是相当于减dp[2][1] = 0(dp初始化为0的)
dp[2][3] = dp[2][2] + dp[3][3] = 2;
dp[3][4] = dp[3][3] + dp[4][4] = 2;
/* len = 3 */
dp[1][3] = dp[1][2] + dp[2][3] - 1 = 3;//其实这里的-1是减去了重复计算的b:也就是dp[2][2]
dp[2][4] = dp[2][3] + dp[3][4] - 1 = 3;//这里的-1是减去了重复计算的c:也就是dp[3][3]
/* len = 3 */
dp[1][4] = dp[1][3] + dp[2][4] - 2 = 3;//这里的-2是减去了重复计算的bc:也就是dp[2][3]

 可以看到

当s[st] == s[ed]时,dp[ st ][ ed ] = dp[ st ][ed - 1] + dp[st + 1][ed] + 1;

当s[st] != s[ed]时,dp[ st ][ ed ] = dp[ st ][ ed - 1 ] + dp[ st + 1 ][ ed ] - dp[ st + 1 ][ ed - 1 ];

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <limits>
#include <set>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#define INF 0x3f3f3f3f

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxN = 1e3 + 5;
const int mod = 10007;
int dp[maxN][maxN];
string s;
void init(int x)
{
    memset(dp, 0, sizeof(dp));
    for(int i = 0; i < x; i ++ )
        dp[i][i] = 1;
}
int main()
{
    int QAQ; scanf("%d", &QAQ);
    for(int Case = 1; Case <= QAQ; Case ++ )
    {
        cin >> s;
        int n = s.size();
        init(n);
        for(int len = 2; len <= n; len ++ )
        {
            for(int st = 0; st < n; st ++ )
            {
                int ed = st + len - 1;
                if(ed > n)
                    break;
                if(s[st] == s[ed])
                    dp[st][ed] = (dp[st][ed - 1] + dp[st + 1][ed] + 1) % mod;
                else
                    dp[st][ed] = (dp[st][ed - 1] + dp[st + 1][ed] - dp[st + 1][ed - 1]) % mod;
            }
        }
        printf("Case %d: %d\n", Case, (dp[0][n - 1] + mod) % mod);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值