迴文數系列題目(經典演算法)

jsjliuyun發表於2014-06-01

迴文數

時間限制:1000 ms  |  記憶體限制:65535 KB
難度:0
描述
請尋找並輸出1至1000000之間的數m,它滿足m、m^2和m^3均為迴文數。迴文數大家都知道吧,就是各位數字左右對稱的整數,例如121、676、123321等。滿足上述條件的數如m=11,m^2=121,m^3=1331皆為迴文數。
輸入
沒有輸入
輸出

輸出1至1000000之間滿足要求的全部迴文數,每兩個數之間用空格隔開,每行輸出五個數


解析:這道題直接模擬就好了,算是迴文數中最簡單的題了,直接寫個判斷迴文數的函式,將整數num逆轉,逆轉的方法就是利用求餘%和/的思想,此題總有一個常錯的地方,就是m的平方和立方可能會超範圍所以一定要用long long 或者_int64即可。

貼一下自己的程式碼

#include <iostream>
using std::endl;
using std::cin;
using std::cout;
bool isHuiWenNumber(long long num)
{
	long long sum=0,temp=num;
	//將整數num逆轉
	while(num)
	{
		sum=sum*10+num%10;
		num/=10;
	}
	if(temp==sum)
		return 1;
	else
		return 0;
}
int main()
{
#ifdef LOCAL
	freopen("input.txt" , "r" , stdin);
	freopen("output.txt" , "w" , stdout);
#endif
	int count = 0;
	for(long long i=1; i<=1000000; ++i)
	{
		long long b=i*i;
		long long c = b*i;
		if(isHuiWenNumber(i) && isHuiWenNumber(b) && isHuiWenNumber(c))
		{
			count++;
			cout << i;
			if(count < 5)
				cout << " ";
			else
			{
				count = 0;
				cout << endl;
			}
		}
	}
	return 0;
}

最長迴文子串

時間限制:1000 ms  |  記憶體限制:65535 KB
難度:4
描述
輸入一個字串,求出其中最長的迴文子串。子串的含義是:在原串連續出現的字串片段。迴文的含義是:正著看和倒著看是相同的,如abba和abbebba。在判斷是要求忽略所有的標點和空格,且忽略大小寫,但輸出時按原樣輸出(首尾不要輸出多餘的字串)。輸入字串長度大於等於1小於等於5000,且單獨佔一行(如果有多組答案,輸出第一組)。
輸入
輸入一個測試資料n(1<=n<=10);
隨後有n行,每行有一個字串。
輸出
輸出所要求的迴文子串。
樣例輸入
1
Confuciuss say:Madam,I'm Adam.
樣例輸出
Madam,I'm Adam

解析:求最長的迴文字串,必須有個陣列來專門記錄去掉符號後每個字元在原字串中的位置,這樣才能在輸出的時候輸出原來的地方,另外,就是在判斷迴文串時,如果去列舉串,字元太多,肯定超時,所以應該去列舉迴文串的中間位置,分奇數迴文串和偶數迴文串。

貼一下自己的程式碼

#include <iostream>
#include <stdlib.h>
#include <string>
#include <ctype.h>
#include <stdio.h>
using std::endl;
using std::cin;
using std::cout;
using std::getline;
using std::string;
const int MAXN = 5000;
int p[MAXN];
char tempStr[MAXN];
int main()
{
#ifdef LOCAL
	freopen("input.txt" , "r" , stdin);
	freopen("output.txt" , "w" , stdout);
#endif
	int n;
	cin >> n;
	//將輸入n後的回車符給吃掉
	getchar();
	while(n--)
	{
		string str;
		int m = 0;
		//從cin讀入一行字元
		getline(cin,str);
		for(int i=0; i<str.length(); ++i)
		{
			if(isalpha(str[i]))
			{
				p[m] = i;
				//忽略大小寫,全部轉換為大寫
				tempStr[m++] = toupper(str[i]);
			}
		}
		//i為迴文串中間的位置,為了提高效率列舉所有可能迴文串的中間位置
		//max儲存迴文串最大的長度
		int maxlegth = 0;
		//儲存最長迴文串在原str中的起始和終止的位置
		int beg , end;
		for(int i=0; i<m; ++i)
		{
			//j為迴文串中離中間位置i的距離
			//迴文串是奇數
			for(int j=0 ; j<=i && i+j <m; ++j)
			{
				if(tempStr[i-j] != tempStr[i+j])
					break;
				if(2*j+1 > maxlegth)
				{
					maxlegth = 2*j+1;
					//記錄當前迴文串的起始和終止位置在原字串str中的位置
					beg = p[i-j];
					end = p[i+j];
				}
			}
			//迴文串是偶數
			for(int j=0; j<=i && i+j+1<m; ++j)
			{
				if(tempStr[i-j] != tempStr[i+j+1])
					break;
				if(2*j+2 > maxlegth)
				{
					maxlegth = 2*j+2;
					//記錄當前迴文串的起始和終止位置在原字串str中的位置
					beg = p[i-j];
					end = p[i+j+1];
				}
			}
		}
		//輸出最長的迴文字串
		for(int i=beg; i<=end; ++i)
			cout << str[i];
		cout << endl;
	}
	return 0;
}

少年 DXH

時間限制:1000 ms  |  記憶體限制:65535 KB
難度:2
描述
大家都知道,DXH 幼時性格怪癖,小朋友都不喜歡和他玩,這種情況一直到 DXH 的少年時期也沒有改變。
少年時期的 DXH 迷上了"迴文串",“迴文串”是指正著讀倒著讀都一樣的字串。DXH一個人的時候喜歡在地上隨便寫一個字串 S,然後在這個字串的右邊新增儘量少的字元(可以不新增,就是 0 個),使得這個字串變成“迴文串”。但玩的時間長了,DXH 的手也酸了,聰明的你能幫他寫一個程式,算出這個新增最少字元形成的迴文串嗎?
一個字串 S[1..L]被稱為迴文串,當且僅當 S[i] = S[L - i + 1] (1 <= i <= L)。
輸入
第一行,一個 T (T <= 100),表示有 T 個字串需要你判斷
之後 T 行,每行一個字串 S。
S 的長度|S|滿足 1 <= |S| <= 50,且 S 只由小寫字母'a' -'z'組成。
輸出
對於每個字串,輸出一行,每行一個字串 S', 是在 S 右側新增最少的字元形成的迴文串。
樣例輸入
5
add
cigartragic
dxhisgirl
acaba
abczyxyz
樣例輸出
adda
cigartragic
dxhisgirlrigsihxd
acabaca
abczyxyzcba
來源
山東大學 ACM/ICPC 校賽高年級組試題 2012

解析:這道題糾結了很久,最後沒想到那麼簡單。

錯誤的想法:先開始是還是按照上題最長迴文字串的思想來模擬迴文串的中心位置,由於只能在字串的最右邊插入字元,所以我判斷迴文串的中心位置應該在偏右側,也就是中心位置右邊的字元數應該大於或者等於左邊,然後還有當有匹配長度變大時更新,因為儘量找到偏右側的迴文串的中心位置,所以中心位置的列舉應該倒著來,從後向前列舉,但是當迴文串是偶數的時候還是會出現問題,當為偶數的時候還需要判斷迴文串中心的位置在最右側還是在中間,因為這都影響著最後填充字元的數量,反正感覺最後糾結的自己都寫不下去了,開始思路挺清晰的,但是提交了幾次wa,想了多組測試資料才發現自己程式碼漏洞太多,果然最後還是放棄了哈!

正解:很簡單,既然說新增最少的字元,如果需要新增字元的話肯定是對稱著字串最左邊新增的,所以可以列舉新增字元的數量從少到多,當是迴文串的時候就可以停止了,此時當然就是新增最少的字元數量了哈!

感悟:這是太笨了,感覺自己受題目的影響,老想不到正確的地方,自己做的題也不少,提升感覺不大,也不知道為什麼,還是從基礎學起,打好基礎再說哈!

貼一下ac的程式碼哈

#include <iostream>
#include <string>
using std::endl;
using std::cin;
using std::cout;
using std::string;
//判斷是否為迴文串
int is_HuiWenStr(string s)
{
	int j = s.length() - 1;
	for(int i=0; i<j; ++i , --j)
	{
		if(s[i] != s[j])
		{
			return 0;
		}
	}
	return 1;
}
int main()
{
#ifdef LOCAL
	freopen("input.txt" , "r" , stdin);
	freopen("output.txt" , "w" , stdout);
#endif
	int N;
	cin >> N;
	while(N--)
	{
		string str , result;
		cin >>str;
		if(is_HuiWenStr(str))
		{
			cout << str << endl;
		}else{
			int length = str.length();
			//列舉新增的字元數量
			for(int i=0;i<length; ++i)
			{
				result = str;
				for(int j=i;j>=0;--j)
				{
					result+= str[j];
				}
				if(is_HuiWenStr(result))
				{
					cout << result << endl;
					break;
				}
			}
		}
	}
}


相關文章