hdu4632Palindrome subsequence (求回文数,区间DP)

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
is a subsequence of. (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 =
and Y = , if there exist an integer i (1<=i<=k) such that xi != yi, the subsequence X and Y should be consider different even if S[sub]xi[/sub] = S[sub]yi[/sub]. 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
#include<stdio.h>
#include<string.h>
int t,dp[1005][1005],c=0;
int main()
{
    char str[1005];
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s",str);
        int len=strlen(str);
        memset(dp,0,sizeof(dp));
        for(int i=0;i<len;i++)
        dp[i][i]=1;
        for(int r=1;r<len;r++)
        for(int i=0;i<len-r;i++)
        {
            int j=i+r;
            dp[i][j]=(dp[i+1][j]+dp[i][j-1]-dp[i+1][j-1]+10007)%10007;
            if(str[i]==str[j])
            dp[i][j]=(dp[i][j]+dp[i+1][j-1]+1)%10007;
        }
        printf("Case %d: %d\n",++c,dp[0][len-1]);
    }
}
时间: 2024-11-12 18:40:01

hdu4632Palindrome subsequence (求回文数,区间DP)的相关文章

回文串区间dp

UVa 10739 String to Palindrome(经典回文串区间DP) 题意: 给定一个字符串,可以对其进行删除,插入,替换操作. 问最少经过几次操作,可以使这个字符串变成回文字符串. 思路: 看得别人的 题解,最优化问题,用较为直接的方法处理时发现情况很复杂,很多时候就要考虑动态规划了.先从整体出发,由大到小,看往少一个两个元素的情况进行最优递归,如何得到结果. (这里区间DP即是不断向两侧扩大规模) (1)如果最外层两个字符相同,s[0]==s[n],那么这两个字符外侧肯定不用考

UVa 10617 Again Palindrome(回文串区间DP)

UVa 10617 Again Palindrome(经典回文串区间DP) 题意: 给定一个字符串s,对s进行删除操作,使得剩下的子串是回文字符串,问最多有多少种这种子串. 思路: 涉及到回文字符串,首先要想到的肯定是区间DP,如何写出状态转移方程? 直接从题意切入:dp[i, j]表示区间[i, j]最多有多少个这样的子串. 1. s[i] == s[j] 去掉s[i],则一个子问题就是dp[i+1, j]; 去掉s[j],另一个子问题就是dp[i, j-1]; 显然这两个子问题是会有重叠的,

求回文数

1.问题梗概: 寻找并输出11~999之间的数m,它满足m,m平方,m立方均为回文数. 2:问题分析: 首先,个位数一定不是回文数,因为不存在对称问题.当最低位(个位)和最高位(百位)数字相同时,则说明这个数是回文数.比如151,969,1441,15651等等.那我们怎样从编写程序来判断这个数是否为回文数呢,则可以通过取余的方式来获得一个新数,从而与原数相比较. 代码如下: int Palindrome(int x) { int number=x; int m=0; while (number

最长回文子序列 区间dp

J - 买票回家啦 Time Limit:1000MS    Memory Limit:65535KB    64bit IO Format: SubmitStatusPracticeNBUT 1586 Description 集训要结束了,同学们就准备回家了.好舍不得回家阿.(那就再待一个月嘛,就这么愉快地决定了.)超哥要回家了,可是他没有挤进12306官网, 可怜的他就随便找了个能代购车票的网站.结果,当他付钱时傻眼了,这个网站竟然要验证码.验证码嘛就照着样子输入就好了呀,哦不,这个网站管理

bzoj 1710: [Usaco2007 Open]Cheappal 廉价回文【区间dp】

只要发现添加一个字符和删除一个字符是等价的,就是挺裸的区间dp了 因为在当前位置加上一个字符x就相当于在他的对称位置删掉字符x,所以只要考虑删除即可,删除费用是添加和删除取min 设f[i][j]为从i到j的价格,长度从小到大枚举更新就行了 f[i][j]=min(f[i][j-1]+cost[s[j]],f[i+1][j]+cost[s[i]]),如果s[i]==s[j]还能和f[i+1][j-1]取个min cpp #include<iostream> #include<cstdio

无聊试试各牛B语言: 求回文数

环境: CPU :  I5-4200 MEM: 4G OS: 64bit  -- Windows (10)   &  Ubuntu (trusty) C 语言 1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<time.h> 4 5 bool ishuiwen(int n) { 6 int sn = 0; 7 sn = n; 8 int tn = 0; 9 while (sn != 0) { 10 tn =

回文数 第N个回文数

判断回文数还是不难,如果能转为字符串就更简单了. 如果是求第N个回文数呢. 12321是一个回文数,这里先考虑一半的情况. 回文数的个数其实是有规律的.如: 1位回文数: 9个 2位回文数: 9个 3位回文数: 90个 4位回文数: 90个 5位回文数: 900个 6位回文数: 900个 … 我们看到9.90.900,是不是很有规律,那是什么原因?很简单,我们把回文数拆开两半 [123321]来看.两半的变化一样的,那我们只算其中一半就行了.首位不能是0,所以左半最小为 100,最大为999,共

for语句的强化(水仙花,九九乘法表,回文数等)

一.输出如下图形:11 21 2 31 2 3 41 2 3 4 51 2 3 4 5 61 2 3 4 5 6 71 2 3 4 5 6 7 81 2 3 4 5 6 7 8 9 public class five { public static void main(String[] args) {  // TODO Auto-generated method stub    for(int a=1;a<=9;a++){     for(int  b=1;b<=a;b++){      Sy

经典回文数

#include<iostream> using namespace std; //经典求回文数的问题 //打印所有不超过n(取n<256)的其平方具有对称性质的数(也称回文数). int len[10]; int i; int main(){ for(int m = 1;m < 256;m++){ int k = 0;//记录反向的回文的加和 int square = m*m; int t = 1;// for(i = 0;square!=0;i++){ len[i] = squ