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

【编程之美挑战赛】回文字符序列(区间dp)

2015-04-18 15:38 267 查看
给定字符串,求它的回文子序列个数。回文子序列反转字符顺序后仍然与原序列相同。例如字符串aba中,回文子序列为"a", "a", "aa", "b", "aba",共5个。内容相同位置不同的子序列算不同的子序列。


输入

第一行一个整数T,表示数据组数。之后是T组数据,每组数据为一行字符串。


输出

对于每组数据输出一行,格式为"Case #X: Y",X代表数据编号(从1开始),Y为答案。答案对100007取模。


数据范围

1 ≤ T ≤ 30

小数据

字符串长度 ≤ 25

大数据

字符串长度 ≤ 1000

样例输入
5
aba
abcbaddabcba
12111112351121
ccccccc
fdadfa

样例输出

Case #1: 5
Case #2: 277
Case #3: 1333
Case #4: 127
Case #5: 17


hint:5:


1.f 
2.d 
3.a 
4.f 
5.d 
6.a 
7.ff 
8.dd 
9.aa 
10.fdf 
11.faf 
12.fdf 
13.dad 
14.ada 
15.afa 
16.fddf 
17.fdadf


http://hihocoder.com/contest/msbop2015qual/problem/2

大神是用dp做的。。

用dp[i][j]表示这一段里有多少个回文串,那首先dp[i][j]=dp[i+1][j]+dp[i][j-1],但是dp[i+1][j]和dp[i][j-1]可能有公共部分,所以要减去dp[i+1][j-1]。如果str[i]==str[j]的话,还要加上dp[i+1][j-1]+1。


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include<cmath>
#define mod 100007  
using namespace std;
int dp[1005][1005];
char str[1005];
int main(){
	int t;
	cin>>t;
	int cnt=0;
	while(t--){
		string x;
		cin>>x;
		for(int i=0;i<x.length();++i){
			dp[i][i]=1;
		}
		for(int i=1;i<x.length();++i){
			for(int j=i-1;j>=0;--j){
				if(x[i]==x[j])
					dp[j][i]=(dp[j+1][i]+dp[j][i-1]+1)%mod;
				
				else
					dp[j][i]=(dp[j+1][i]+dp[j][i-1]-dp[j+1][i-1]+mod)%mod; 
			}
		}
		printf("Case #%d: %d\n",++cnt,dp[0][x.length()-1]); 
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: