[編程之美]資格賽 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


歡迎大家與我交流.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章