zoukankan      html  css  js  c++  java
  • 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
    ",t,dp[1][len]%mod);
        }
        return 0;
    
    }
  • 相关阅读:
    ASP.NET Core Docker部署
    Asp.net core WebApi 使用Swagger生成帮助页实例
    C#图片文字识别
    C#实现rabbitmq 延迟队列功能
    Windows下当地RabbitMQ服务的安装
    看大数据时代下的IT架构(1)业界消息队列对比
    查看sqlserver被锁的表以及如何解锁
    如何让win2008服务器显示中文无乱码
    Lucene.Net的服务器封装+APi组件 (开源)
    Oracle学习系列4
  • 原文地址:https://www.cnblogs.com/-citywall123/p/10914922.html
Copyright © 2011-2022 走看看