HDU-4632 http://acm.hdu.edu.cn/showproblem.php?pid=4632

http://acm.hdu.edu.cn/showproblem.php?pid=4632

题意:

一个字符串,有多少个subsequence是回文串。

别人的题解:

用dp[i][j]表示这一段里有多少个回文串,那首先dp[i][j]=dp[i+1][j]+dp[i][j-1],但是dp[i+1][j]和dp[i][j-1]可能有公共部分,所以要减去dp[i+1][j-1]。

如果str[i]==str[j]的话,还要加上dp[i+1][j-1]+1。

但是自己却是这样想的,把每个区间都要看是否为回文串,在dp[i][j]=dp[i+1][j]+1。我的想法是错误的,我忽略了每个区间都是一个递推的过程。

比如:aaa,a是一个回文串则外面2个aa只要判断是否相等就可以了就可以。如果区间两头是相等的,则要加上dp[j+1][i-1]+1,因为首尾是可以组成一个回文子串的,而且首尾可以与中间任何一个回文子串组成新的回文子。

其结果要取余,利用来了 dp[i][j]=(dp[i][j]+10007)%10007;

Palindrome subsequence

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65535 K (Java/Others)
Total Submission(s): 2246    Accepted Submission(s): 895

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

Source

2013 Multi-University Training Contest 4

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int dp[1005][1005];
int main()
{
    int t,k,i,j,g,len,r,p,q,e,m,b;
     char str[1005];
     cin>>q;
     for(r=1;r<=q;r++)
     {
         memset(dp,0,sizeof(dp));
         scanf("%s",str);
         len=strlen(str);
         for(i=0;i<len;i++)
            dp[i][i]=1;//初始化,单个字符肯定是一个回文子串
         for(k=0;k<len;k++)
           {
             for(i=0;i<len-k;i++)
             {
                 j=i+k;
                 dp[i][j]=dp[i+1][j]+dp[i][j-1]-dp[i+1][j-1];////如果区间两头是相等的,则要加上dp[j+1][i-1]+1,
                 //因为首尾是可以组成一个回文子串的,而且首尾可以与中间任何一个回文子串组成新的回文子串
                 if(str[i]==str[j])
                     dp[i][j]+=dp[i+1][j-1]+1;
                 dp[i][j]=(dp[i][j]+10007)%10007;//结果取余。
              }
           }

         printf("Case %d: %d\n",r,dp[0][len-1]);
     }
    return 0;
}
/*
4
a
aaaaa
goodafternooneveryone
welcometoooxxourproblems
Case 1: 1
Case 2: 31
Case 3: 421
Case 4: 960
*/

HDU-4632 http://acm.hdu.edu.cn/showproblem.php?pid=4632

时间: 2024-08-10 14:57:43

HDU-4632 http://acm.hdu.edu.cn/showproblem.php?pid=4632的相关文章

HDU 4911 http://acm.hdu.edu.cn/showproblem.php?pid=4911(线段树求逆序对)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4911 解题报告: 给出一个长度为n的序列,然后给出一个k,要你求最多做k次相邻的数字交换后,逆序数最少是多少? 因为每次相邻的交换操作最多只能减少一个逆序对,所以最多可以减少k个逆序对,所以我们只要求出原来的序列有多少个逆序对然后减去k再跟0取较大的就可以了. 因为数据范围是10的五次方,所以暴力求肯定会TLE,所以要用n*logn算法求逆序对,n*logn算法有几种可以求逆序对的: 线段树,树状数

http://acm.hdu.edu.cn/showproblem.php?pid=2825

地址:http://acm.hdu.edu.cn/showproblem.php?pid=2825 题目: Wireless Password Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 6862    Accepted Submission(s): 2279 Problem Description Liyuan lives in a

HDU 5652 二分加搜索 http://acm.split.hdu.edu.cn/showproblem.php?pid=5652

Problem Description A long time ago there are no himalayas between India and China, the both cultures are frequently exchanged and are kept in sync at that time, but eventually himalayas rise up. With that at first the communation started to reduce a

字符串处理 最佳裁判http://acm.hdu.edu.cn/showproblem.php?pid=4520

#include <stdio.h> int main() { int N; scanf("%d",&N);//先输入 double a[N],b[N],c,d=0,o[N-1],e,f;//这里定义3个数组下面会用到 for (int i=0; i<N; i++) { scanf("%lf",&a[i]); b[i]=a[i];//得到2个一样的数组,因为有一个数组因为排序要改变 } for (int i=0; i<N-1;

Help him http://acm.hdu.edu.cn/showproblem.php?pid=5059

题目是昨天晚上的BC.昨天晚上一直卡在第二题,囧. 今天看到题解之后,觉得自己想的也是差不多的,该考虑的也考虑到的.究竟是为什么会错.然后我就改了交,改了交.终于让我改对了一次,我找到了自己的代码中哪段有问题. 接下来上代码: wa code: int but=0; if(!sig) but=1; else but=0; long long c=0,r=1; for(int i=strlen(str)-1; i>=but; i--) { //not digit if(str[i]<'0'||s

饭卡 (背包01) http://acm.hdu.edu.cn/showproblem.php?pid=2546

/* 从一组数据中选出n个数,使这n个数的和最接近一个值x, 背包问题, 从一系列菜中,从最贵的菜(MAX)之外中选出几个菜,使菜的总价格sum最接近money-5:money-sum-MAX; 钱数相当于背包总容量,菜相当于价值和体积一样物品: */ #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; int d

HDU 1455 http://acm.hdu.edu.cn/showproblem.php?pid=1455

#include<stdio.h> #include<stdlib.h> #include<math.h> #include<string.h> #define N 70 int f, vis[N], v, n, a[N]; int cmp(const void *a, const void *b) { return *(int *)b - *(int *)a; } void DFS(int w, int sum) { int i; if(sum == 0)

HDU 1285 确定比赛名次 http://acm.split.hdu.edu.cn/showproblem.php?pid=1285

Description 有N个比赛队(1<=N<=500),编号依次为1,2,3,....,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直接获得每个队的比赛成绩,只知道每场比赛的结果,即P1赢P2,用P1,P2表示,排名时P1在P2之前.现在请你编程序确定排名. Input 输入有若干组,每组中的第一行为二个数N(1<=N<=500),M:其中N表示队伍的个数,M表示接着有M行的输入数据.接下来的M行数据中,每行也有两个整数P1,P2表示

HDU5122 http://acm.hdu.edu.cn/showproblem.php?pid=5122

1 #include <stdio.h> 2 #include <string.h> 3 int s[1011010]; 4 int main() 5 { 6 int T,sum,n,f; 7 scanf("%d",&T); 8 f=0; 9 while(T--) 10 { 11 f++; 12 scanf("%d",&n); 13 for(int i=0;i<n;i++) 14 { 15 scanf("%d&