您的位置:首页 > 编程语言

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

2015-04-21 19:53 246 查看
注意这一题里面的子序列不同于子串,子串必须是连续的,子序列可以不连续。

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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: