hdu-4632 Palindrome subsequence (回文子序列计数)

Posted Luke_Ye

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu-4632 Palindrome subsequence (回文子序列计数)相关的知识,希望对你有一定的参考价值。

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4632

问题要求回答一串字符串中回文子序列的数量,例如acbca就有 a,c,b,c,a,cc,aa,aca,aca(注意这两个aca的c是不同位置的c,都要累计),aba,cbc,acca,acbca.共13种。

我们如果构造dp[i][j]为区间从i-j的回文子序列个数,当i==j时dp[i][j]=1,当i!=j时,如果字符串i,j位相等,他们便可以从dp[i+1,j-1]转移而来,即dp[i][j]=dp[i+1][j-1]*1+1(这里特地写成*1,因为不是单纯的计数+1,是原先区间[i+1,j-1]的所有回文子序列都可以在左右增加一个当前字符构成新的回文序列,同时还加入单独以两个当前字符构成的回文序列)。这里就计算了以当前字符作为左右临界的回文序列个数,除此之外还需要继承子区间所有的回文序列,这个就与字符i,j是否相等无关了。注意这里不能直接累加dp[i+1][j-1],因为会忽略i+k与j以及i与j-k为左右临界的子序列数。因此dp[i][j]+=dp[i+1][j]+dp[i][j-1]-dp[i+1][j-1](两区间累加,去除重复区间).

#include <iostream>
#include <cstdio>
#include <vector>
#include <map>
#include <algorithm>
#include <queue>
#include <cstring>
#define LL long long int
using namespace std;

const int mod=10007;
int dp[1005][1005];
int main(){
    int n,k;
    cin.sync_with_stdio(false);
    cin>>n;
    int cas=1;
    while(n--)
    {
        string s;
        cin>>s;
        for(int i=0;i<s.length();i++)
            for(int j=0;j<s.length();j++)
                dp[i][j]=(i==j);
        for(int i=s.length()-1;i>=0;i--)
        {
            for(int j=0;j<s.length();j++)
            {
                if(i>=j)
                    continue;
                dp[i][j]=(dp[i+1][j]+dp[i][j-1]+mod-dp[i+1][j-1])%mod;
                if(s[i]==s[j])
                    dp[i][j]+=dp[i+1][j-1]+1;
                dp[i][j]%=mod;
            }
        }
        cout<<"Case "<<cas++<<": "<<dp[0][s.length()-1]<<endl;
    }
    return 0;
}

 

以上是关于hdu-4632 Palindrome subsequence (回文子序列计数)的主要内容,如果未能解决你的问题,请参考以下文章

hdu-4632 Palindrome subsequence (回文子序列计数)

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

HDU 4632 Palindrome subsequence(区间DP求回文子序列数)

HDU 4632 Palindrome subsequence (区间DP)

Palindrome subsequence (区间DP)

hdu4632 回文子序列