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 from another sequence by deleting some elements without changing the order of the remaining elements. For example, the sequence <A, B, D> is a subsequence of <A, B, C, D, E, F>.
(http://en.wikipedia.org/wiki/Subsequence)

Given a string S, your task is to find out how many different subsequence of S is palindrome. Note that for any two subsequence X = <Sx1, Sx2, ..., Sxk> and Y = <Sy1, Sy2, ..., Syk> , if there exist an integer i (1<=i<=k) such that xi != yi, the subsequence X and Y should be consider different even if Sxi = Syi. Also two subsequences with different length should be considered different.

Input

The first line contains only one integer T (T<=50), which is the number of test cases. Each test case contains a string S, the length of S is not greater than 1000 and only contains lowercase letters.

Output

For each test case, output the case number first, then output the number of different subsequence of the given string, the answer should be module 10007.

Sample Input

4

a

aaaaa

goodafternooneveryone

welcometoooxxourproblems

Sample Output

Case 1: 1

Case 2: 31

Case 3: 421

Case 4: 960

大致题意是给定一个字符串,求这个字符串的回文子序列个数,最后的答案要%10007

题解:用dp[i][j]表示区间[i,j]回文子序列的个数

1、首先,初始化dp[i][j]=1;

2、然后预处理子结构,如果s[i]==s[i+1],则dp[i][i+1]=3(a,a,aa),否则 dp[i][i+1]=2  (a,b)

3、最后用区间DP处理:

如果s[i]==s[j],即子序列首尾相等,那么这段子序列区间内的所有回文子序列都可以和首尾元素再构成新的回文子序列,除此之外 s[i]和s[j]这两个元素也可以构成一个回文子序列

dp[i][j]=(dp[i+1][j]+dp[i][j-1]+1)%mod;

如果s[i]!=s[j],

dp[i][j]=(dp[i+1][j]+dp[i][j-1] dp[i+1][j-1]+mod)%mod;   (容斥原理,中间部分会计算两遍,所以要减去dp[i+1][j-1])

注意:做减法的时候,可能会有负数,为了使%不出现问题,我们需要先加mod再%mod

还要注意一下数据类型的问题,这道题目如过把dp[i][j]的类型直接定义为long long 会超时

1、因为long long 类型 运算没有int快 所以要改为int型 还有取模的数mod也必须要是int型 如果mod是long long的话也会超时.

2、能用int的就不要用long long,因为如果用了long long 就有可能超时;原来一直以为用ll不会爆范围,就总是用ll,现在发现了,一直用ll会爆时间,

尤其是在这种矩阵快速幂的题里,绝对要注意!!!

#include<iostream>
#include<string.h>
#include<string>
#include<math.h>
#define ll long long
#define mod 10007
using namespace std;
int n,t;
int dp[2005][2005];
char s[1005];
ll min(ll a,ll b)
{
    return a<b?a:b;
}

int main()
{
    cin>>n;
    t=0;
    while(n--)
    {
        t++;
        scanf("%s",s+1);
        int len=strlen(s+1);
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=len;i++)//初始化
            dp[i][i]=1;
        for(int i=1;i<len;i++)//预处理
        {
            if(s[i]==s[i+1])
                dp[i][i+1]=3;//a,a,aa
            else
                dp[i][i+1]=2;//a,b
        }
        for(int l=3;l<=len;l++)
        {
            for(int i=1;i+l-1<=len;i++)
            {
                int j=i+l-1;
                if(j>len)
                    break;
                if(s[i]==s[j])//如果首尾相等,则这段区间内的所有回文子序列都可以和首尾元素再构成新的回文子序列
                    dp[i][j]=(dp[i+1][j]+dp[i][j-1]+1)%mod;
                else
                    dp[i][j]=(dp[i+1][j]+dp[i][j-1]-dp[i+1][j-1]+mod)%mod;

            }
        }
        printf("Case %d: %d\n",t,dp[1][len]%mod);
    }
    return 0;

}

原文地址:https://www.cnblogs.com/-citywall123/p/10914922.html

时间: 2024-07-30 00:51:49

hdu4632 Palindrome subsequence 回文子序列个数 区间dp的相关文章

hdu4757 最长回文子序列(区间DP)

http://acm.hdu.edu.cn/showproblem.php?pid=4745 Problem Description Long long ago, there lived two rabbits Tom and Jerry in the forest. On a sunny afternoon, they planned to play a game with some stones. There were n stones on the ground and they were

HDU 4745 Two Rabbits【非连续最长回文子序列,区间DP】

SubmitStatus Description Long long ago, there lived two rabbits Tom and Jerry in the forest. On a sunny afternoon, they planned to play a game with some stones. There were n stones on the ground and they were arranged as a clockwise ring. That is to

回文子序列个数

时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 给定字符串,求它的回文子序列个数.回文子序列反转字符顺序后仍然与原序列相同.例如字符串aba中,回文子序列为”a”, “a”, “aa”, “b”, “aba”,共5个.内容相同位置不同的子序列算不同的子序列. 输入 第一行一个整数T,表示数据组数.之后是T组数据,每组数据为一行字符串. 输出 对于每组数据输出一行,格式为”Case #X: Y”,X代表数据编号(从1开始),Y为答案.答案对100007取模. 数据范围 

2015编程之美资格赛 回文子序列个数

时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 给定字符串,求它的回文子序列个数.回文子序列反转字符顺序后仍然与原序列相同.例如字符串aba中,回文子序列为”a”, “a”, “aa”, “b”, “aba”,共5个.内容相同位置不同的子序列算不同的子序列. 输入 第一行一个整数T,表示数据组数.之后是T组数据,每组数据为一行字符串. 输出 对于每组数据输出一行,格式为”Case #X: Y”,X代表数据编号(从1开始),Y为答案.答案对100007取模. 数据范围 

字符串的回文子序列个数

题目描述 求一个长度不超过15的字符串的回文子序列个数(子序列长度>=1). 输入描述 输入一个长度不超过15的字符串,字符串均由小写字母表示 输出描述 输出其回文子序列个数 样例输入 abaa 样例输出 10 注释 本例中其所有回文子序列为: a,b,a,a,aba,aba,aa,aa,aa,aaa 一个字符串的子序列是指在原字符串上去除某些字符但不破坏余下元素的相对位置(在前或在后)而形成的新字符串. #include<iostream> #include<string>

题目2 : 回文字符序列(区间DP)

时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 给定字符串,求它的回文子序列个数.回文子序列反转字符顺序后仍然与原序列相同.例如字符串aba中,回文子序列为"a", "a", "aa", "b", "aba",共5个.内容相同位置不同的子序列算不同的子序列. 输入 第一行一个整数T,表示数据组数.之后是T组数据,每组数据为一行字符串. 输出 对于每组数据输出一行,格式为"

UVa11404Palindromic Subsequence(最大回文串,区间DP)

Description A Subsequence is a sequence obtained by deleting zero or more characters in a string. A Palindrome is a string which when read from left to right, reads same as when read from right to left. Given a string, find the longest palindromic su

HihoCOder1323 : 回文字符串(区间DP)

回文字符串 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个字符串 S ,最少需要几次增删改操作可以把 S 变成一个回文字符串? 一次操作可以在任意位置插入一个字符,或者删除任意一个字符,或者把任意一个字符修改成任意其他字符. 输入 字符串 S.S 的长度不超过100, 只包含'A'-'Z'. 输出 最少的修改次数. 样例输入 ABAD 样例输出 1 区间DP水题,见铺垫:密码脱落. #include<cstdio> #include<cstdlib

NC13230 合并回文子串(区间dp)

从数据范围不难推出可以用f[][][][],表示由两个字符串来表示的最长大小 并且因为是回文串,所以我们要向头尾加字符,来变大,因为这个是回文子串,也就是连续的一段. #include<iostream> #include<cstdio> #include<algorithm> #include<string> #include<cstring> using namespace std; const int N=55; char s1[55],s