[编程之美]资格赛 B Palindrome

既然这个是资格赛,  时间也比较充裕, 我就讲解一下我做题的过程

Time Limit:
2000ms Case Time Limit:
1000ms Memory Limit:
256MB

Description

Given a string, calculate the number of subsequences that are palindrome. A palindrome is a sequence of characters that reads the same backward or forward. For example, in the string “aba”, there are 7 subsequences “a”, “b”, “a”, “ab”, “aa”, “ba”, “aba”. Only “a”, “b”, “a”, “aa”, “aba” are palindrome. Two subsequences that contain characters from different positions are considered different.

Input

The first line of input contains a single integer T specifying the number of test cases.  In each test case, there is only one line containing a string.

Output

For each test case, output a line containing “Case #X: Y”, where X is the test case number starting from 1, followed by one integer Y indicating the number of palindrome subsequences. Output the answer modulo 100007.

Limits

1 ≤ T ≤ 30

Small

Length of string ≤ 25

Large

Length of string ≤ 1000

Sample Input

5
aba
abcbaddabcba
12111112351121
ccccccc
fdadfa

Sample Output

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

我最先想到的就是枚举法了,  把所有的子列都列举出来, 一一判断它们是不是回文串

枚举的方法即使用二项式, 通过二进制数判断哪些字符应当出现在子列中:

#include <iostream>
#include <string>
using namespace std;

int main(void){
	int T,count=0;
	cin >> T;

	int result[30];
	for (int mem = 0; mem < 30; mem++)
	{

		result[mem] = 0;
	}
	while (count<T)
	{
		char a[1000];
		cin >> a;
		int g = 0;
		while (a[g]!='\0')
		{
			g++;
		}
		int size = g;
		for (int i = 1; i < 1<<size; i++)
		{
			//string sub;
			char* sub;
			sub = (char*)malloc(size*sizeof(char));
			int appear = 0;
			for (int j = 0; j < size; j++)
			{
				
				if ((1 << j)&i){
					sub[appear++] = a[j];
				}
			}
			bool ok = true;
			int ii = 0;
			int jj = appear;
			for (int k = 0; ii <= (int)(jj/2); ii++)
			{
				if (sub[ii]!=sub[jj+k-ii-1])
				{
					ok = false;
				}
			}
			if (ok)
			{
				result[count]++;
			}
		}
		count++; 
	}
	count = 1;
	while (count<=T)
	{
		std::cout <<"Case #"<<count<<": "<< result[count-1] << endl;
		count++;
	}
	return 0;
}

带入sample 是测试成功的, 但是提交之后显示time limited exceeded

想想枚举法, 最大字符串有 长度为1000, 那我要枚举2^1000次, 早就溢出了,  

所以思考更高效的算法

将相同的字符两两配对, 组成一组, 利用递归的思想, 思考这两字符之间有几个其他的字符对

#include <iostream>
#include <string>
#include <vector>

using namespace std;

char a[1000];

int findPalindrome(int floor, int ceil){
	int result = 0;
	for (int i = floor; i <= ceil; i++)
	{
		for (int j = i; j <= ceil; j++)
		{
			if (a[i]==a[j])
			{
				if (i == j || i + 1 == j)
				{
					result += 1;
				}
				else
				{
					result++;
					result += findPalindrome(i+1, j-1);
				}
			}
		}
	}
	return result;
}

int main(void){
	int T, count = 0;
	cin >> T;
	
	int result[30];
	for (int mem = 0; mem < 30; mem++)
	{
		result[mem] = 0;
	}
	while (count<T)
	{
		for (int i = 0; i < 1000; i++)
		{
			a[i] = '\0';
		}
		cin >> a;
		int g = 0;
		while (a[g] != '\0')
		{
			g++;
		}
		result[count] = findPalindrome(0, g-1);
		count++;
	}
	count = 1;
	while (count <= T)
	{
		std::cout << "Case #" << count << ": " << result[count - 1] << endl;
		count++;
	}
	return 0;
}

Accept

欢迎大家与我交流.

    原文作者:Yihui_He
    原文地址: https://blog.csdn.net/qq_21970857/article/details/45112067
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞