HDU4632 Palindrome subsequence 题解 区间DP

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4632
【题目描述】
《回文子串数量》
给你一个长度为N(N≤1000)的字符串,你输出它所有的回文子串的数量(对10007取模)。
只要从字符串 s 中顺序地取出一些字符(不要求连续,可以是 s 本身,不能是空串),不改变他们的顺序的情况下,这个子串是一个回文串,那么他就是一个 s 的回文子串。
【输入格式】
首先是一个数T(T≤50),表示测试用例的数量。
接下来T行,每行包含一个字符串。
【输出格式】
对于每一个字符串,你需要输出它的回文子串数量(由于数据量可能会比较大,所以结果需要对10007取模)。
【样例输入】
4
a
aaaaa
goodafternooneveryone
welcometoooxxourproblems
【样例输出】
Case 1: 1
Case 2: 31
Case 3: 421
Case 4: 960
【题目分析】
涉及的知识点:区间动态规划(区间DP)。
首先我们假设 dp[i][j] 表示字符串 s 的子串 s[i..j] 中包含的回文子串的数量。
我们可以得到:
· 当i<j且s[i]!=s[j]时, dp[i][j] = dp[i][j-1] ∪ dp[i+1][j] (这里“∪”符号表示)两个集合的并,
根据容斥原理,我们可以得到:
  dp[i][j] = dp[i][j-1] ∪ dp[i+1][j] = dp[i][j-1] + dp[i+1][j] - dp[i+1][j-1]
· 当i<j且s[i]==s[j]时,dp[i][j]的构成除了上述部分以外,还有 s[i] + s‘ + s[j] 部分,其中 s‘ 表示 s[i+1..j-1] 中的任意一个回文串 加上一个特殊的空字符串
所以此时:
  dp[i][j] = dp[i][j-1] ∪ dp[i+1][j] + dp[i+1][j-1] + 1 = dp[i][j-1] + dp[i+1][j] + 1
假设字符串的长度为n,坐标从0开始,那么我们最终的答案就是 dp[0][n-1]。
需要注意的一些细节:
因为这里在运算的时候可能会出现负数,所以比较好的解决办法是加上一个 MOD 在进行取模操作,就不会出现负数了。
据此,我们可以编写代码如下:

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
#define MOD 10007
const int maxn = 1001;
int T, n, dp[maxn][maxn];
string s;

int main() {
    cin >> T;
    for (int cas = 1; cas <= T; cas ++) {
        cin >> s;
        n = s.length();
        fill(dp[0], dp[0]+maxn*maxn, 0);
        for (int l = 1; l <= n; l ++) {
            for (int i = 0; i+l-1 < n; i ++) {
                int j = i + l - 1;
                if (l == 1) dp[i][j] = 1;
                else if (s[i] == s[j]) dp[i][j] = (dp[i][j-1] + dp[i+1][j] + 1) % MOD;
                else {
                    dp[i][j] = (dp[i][j-1] + dp[i+1][j] + MOD - (l > 2 ? dp[i+1][j-1] : 0)) % MOD;
                }
            }
        }
        cout << "Case " << cas << ": " << dp[0][n-1] << endl;
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/mooncode/p/10989523.html

时间: 2024-10-09 08:07:15

HDU4632 Palindrome subsequence 题解 区间DP的相关文章

HDU 4632 Palindrome subsequence(区间dp)

Palindrome subsequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65535 K (Java/Others) Total Submission(s): 2595    Accepted Submission(s): 1039 Problem Description In mathematics, a subsequence is a sequence that can be derived

hdu4632 Palindrome subsequence

Palindrome subsequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65535 K (Java/Others)Total Submission(s): 2280    Accepted Submission(s): 913 Problem Description In mathematics, a subsequence is a sequence that can be derived fr

Blocks题解(区间dp)

Blocks题解 区间dp 阅读体验...https://zybuluo.com/Junlier/note/1289712 很好的一道区间dp的题目(别问我怎么想到的) dp状态 其实这个题最难的地方是这道题目的状态怎么设 首先既然是区间dp,那肯定最先想到的状态是 $dp[i][j]$表示消掉区间$[i,j]$上所有的块的最大分数 突然发现这个状态会受区间外和$i$或$j$颜色相同的块的影响 并且转移也并不好转移=_= 所以我们考虑换一种状态... 既然说会受到外面的块的影响?那考虑一种方法来

hdu4632 Palindrome subsequence 回文子序列个数 区间dp

Palindrome subsequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65535 K (Java/Others)Total Submission(s): 4513    Accepted Submission(s): 1935 Problem Description In mathematics, a subsequence is a sequence that can be derived f

LightOJ1044 Palindrome Partitioning(区间DP+线性DP)

问题问的是最少可以把一个字符串分成几段,使每段都是回文串. 一开始想直接区间DP,dp[i][j]表示子串[i,j]的答案,不过字符串长度1000,100W个状态,一个状态从多个状态转移来的,转移的时候要枚举,这样时间复杂度是不可行的. 然后我就想降维度了,只能线性DP,dp[i]表示子串[0,i]的答案.这样可以从i-1转移到i,str[i]单独作一段或者str[i]能和前面的组成回文串,方程如下: dp[i]=min(dp[i-1]+1,dp[j-1]+1) (子串[j,i]是回文串) 现在

1044 - Palindrome Partitioning(区间DP)

题目大意: 给你一个字符串,问这个字符串最少有多少个回文串. 区间DP直接搞 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<cmath> #include<queue> #include<vector> #include<map> using namespace std; typedef lo

luogu4302字符串折叠题解--区间DP

题目链接 https://www.luogu.org/problemnew/show/P4302 分析 很明显一道区间DP题,对于区间\([l,r]\)的字符串,如果它的字串是最优折叠的,那么它的最优结果要么是所有分割出的字串最优结果之和,要么是在断点处恰好有这个区间的周期串可以进行折叠,折叠后产生的结果 状态转移 for(ri len=2;len<=n;len++){//枚举长度,套路 for(l=1;l<=n-len+1;l++){ r=l+len-1; for(ri k=l;k<r

POJ2955 Brackets 题解 区间DP

题目链接:http://poj.org/problem?id=2955[题目描述]<规则的括号序列>我们定义一个字符串序列为“规则的括号序列”当且仅当它满足如下条件:1.空字符串是规则的括号序列:2.如果字符串 s 是一个规则的括号序列,那么 (s) 和 [s] 也是规则的括号序列:3.如果字符串 a 和 b 都是规则的括号序列,那么 ab 也是规则的括号序列:4.除此之外的字符串都不能称为规则的括号序列.举个例子,下面的这些字符串都是规则的括号序列: (), [], (()), ()[],

POJ 1651 Multiplication Puzzle 题解 区间DP

题目链接:http://poj.org/problem?id=1651[题目描述]<乘法谜题>乘法谜题源自这样一个背景,我们有一行 n 张牌,平铺在桌面上,每张牌的牌面上都标有一个正整数.玩家的初始得分是 0,他接下来要进行 n-2 次操作,每次操作他都需要从桌面上取出一张牌,然后他的得分会加上他取出的这张牌与取出的这张牌的左边的牌以及取出的这张牌的右边的牌的乘积.在第 n-2 次操作结束后,桌面上将会只剩下两张牌.你的目的是帮助玩家决定取牌的顺序,使得玩家的最终得分最小.举个例子,如果一开始