编程之美2015资格赛 B.回文字符序列

来源:互联网 发布:图象处理算法 编辑:程序博客网 时间:2024/05/17 01:42

注意这一题里面的子序列不同于子串,子串必须是连续的,子序列可以不连续。
dp[i][j]表示原字符串[i,j]之间的回文子序列个数,那么状态从dp[i+1][j-1]转移到dp[i][j]时:
如果s[i]==s[j]那么将dp[i+1][j-1]里面的回文子串最两边加上s[i]和s[j]仍然可以构成回文子串,所以会增加dp[i+1][j-1]+1个回文子串,+1是因为s[i]s[j]是回文的。再根据容斥原理,可以得出:dp[i][j]=dp[i+1][j]+dp[i][j-1]-dp[i+1][j-1]+dp[i+1][j-1]+1;
如果s[i]!=s[j],那么dp[i][j]的回文子串数可以直接通过容斥原理得出,即dp[i][j]=dp[i+1][j]+dp[i][j-1]-dp[i+1][j-1]

边界条件是长度为1的子串,dp[i][i]=1;

#include <iostream>#include<stdio.h>#include<vector>#include <algorithm>#include<cmath>#include <cstring>#include <string>using namespace std;long long dp[1010][1010];char str[1010];int ca=1;const int mod=100007;void solve(){    int len=strlen(str);    memset(dp,0,sizeof(dp));    for(int i=0;i<len;i++) dp[i][i]=1;    for(int i=len-1;i>=0;i--)    {        for(int j=i+1;j<len;j++)        {            if(str[i]==str[j])            {              //  dp[i][j]=dp[i+1][j]+dp[i][j-1]-dp[i+1][j-1]+dp[i+1][j-1]+1;              dp[i][j]=dp[i+1][j]+dp[i][j-1]+1;            }            else            {                dp[i][j]=dp[i+1][j]+dp[i][j-1]-dp[i+1][j-1];            }            dp[i][j]+=mod;            dp[i][j]%=mod;        }    }    printf("Case #%d: %d\n",ca++,dp[0][len-1]);}int main(){    //freopen("input.txt","r",stdin);    int t=0;    scanf("%d",&t);    while(t--)    {        scanf("%s",&str);        solve();    }    return 0;}







0 0