Best Compression Algorithms(網易遊戲2015筆試題)

Question

時間限制:10000ms
單點時限:1000ms
內存限制:256MB

描述

易信是由網易和電信聯合開發的一款即時通訊軟件。除了語音聊天,免費電話等新功能以外,傳統的文字信息聊天功能也得以保留,因此每天都有大量的文字信息需要在服務器中存儲,中轉。

小Y是一名負責處理文字信息的易信工程師,每天他都要和字符串打交道。爲了提高存儲和傳輸效率,小Y在課餘時間經常會去研究字符串的存儲方法。通過內部使用的一種統一的加密算法,所有的文字信息首先都會被轉化成只包含大寫字母['A'...'Z']的字符串。爲了壓縮這個加密後的字符串,小Y最近想出了兩個存儲的規則:

(1)如果字符串中有連續相同的大寫字母,它們可以選擇用"字符+出現次數"的方式替代。如字符串'AABCCCCDD',可以用'A2BC4D2'表示,也可以用'A2BC2C2DD'表示。

(2)如果字符串中有連續出現的模式串(模式串長度大於1),它們可以選擇用"(模式)+出現次數"的方式替代。如字符串'FABCABCABCE',可以用'F(ABC)3E'表示,也可以用'F(ABC)2ABCE'表示。

上述規則中的"連續"均指出現次數大於1,規則(2)中的括號後一定是一個大於1的數值,代表出現次數。

綜合上述兩個規則,字符串'AABAABFAABAABFG'可以用'((A2B)2F)2G'表示。小Y保證輸出的壓縮串符合上述的兩個規則,以下類型的非法字符串不會出現:

'(A)5': 括號冗餘

'A1A4': 數字1冗餘

'A((AA))2': 括號冗餘

(ABC)1: 括號和數字1冗餘

對於給定的一個用上述規則壓縮後的字符串,對應的原串是唯一的。小Y想知道這個字符串原來的長度是多少,以此計算壓縮倍率。你能幫助他嗎?

輸入

第一行是整數T(T <= 100),表示下面有T組數據。之後T行,每行爲一組數據,每組數據爲一個字符串。

每個字符串只會包含26個大寫字母['A'...'Z'],數字['0'...'9']和左右括號['(', ')']。

保證輸入數據一定合法,括號內的模式串長度一定大於1,表示出現次數的數字一定大於1,且字符串長度L <= 100。

輸出

輸出T行,每行對應一個數據的輸出結果,表示字符串的實際長度。

保證每個字符串展開後的長度不超過109

樣例輸入
4
(AA)2A
((A2B)2)2G
WANGYI
A2BC4D2
樣例輸出
5
13
6
9

My Solution

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

using namespace std;

/*得到數字,並讓指針指向最後一個數*/
int getDig(const string& str, int& idx)
{
	int dig = 0;
	for (; idx < str.size(); ++idx)
	{
		if (str[idx] >= '0' && str[idx] <= '9')	//數字
		{
			dig = dig * 10 + str[idx] - '0';
		}
		else    // 不是數字
		{
			--idx;
			break;
		}
	}
	return dig;
}

int countLength(const string& str, int& idx)
{
	int score = 0;
	int sSub = 0;
	for (; idx < str.size(); ++idx)
	{
		char c = str[idx];
		if (c >= 'A' && c <= 'Z')	//字符
		{
			++score;
		}
		else if (c == '(')
		{
			++idx;
			sSub = countLength(str, idx);
		}
		else if (c == ')')
		{
			return score;
		}
		else    // 數字
		{
			if (str[idx - 1] == ')')	//跟在模式串後面
			{
				int dig = getDig(str, idx);
				score += dig * sSub;
			}
			else
			{
				int dig = getDig(str, idx);
				score += dig - 1;
			}
		}
	}
	return score;
}

int main()
{
	/*讀取字符串*/
	int t;
	vector<string> lines;
	cin >> t;
	for (int i = 0; i < t; ++i)
	{
		string line;
		cin >> line;
		lines.push_back(line);
	}

	for (auto str : lines)
	{
		int start = 0;
		cout << countLength(str, start) << endl;
	}

    return 0;
}


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